Skip to content

Fix tslib resolutions #58451

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 2 commits into from
May 7, 2024
Merged
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
28 changes: 20 additions & 8 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32191,12 +32191,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
const errorMessage = isClassic
? Diagnostics.Cannot_find_module_0_Did_you_mean_to_set_the_moduleResolution_option_to_nodenext_or_to_add_aliases_to_the_paths_option
: Diagnostics.Cannot_find_module_0_or_its_corresponding_type_declarations;
// Synthesized JSX import is either first or after tslib
const jsxImportIndex = compilerOptions.importHelpers ? 1 : 0;
const specifier = file?.imports[jsxImportIndex];
if (specifier) {
Debug.assert(nodeIsSynthesized(specifier) && specifier.text === runtimeImportSpecifier, `Expected sourceFile.imports[${jsxImportIndex}] to be the synthesized JSX runtime import`);
}
const specifier = getJSXRuntimeImportSpecifier(file, runtimeImportSpecifier);
const mod = resolveExternalModule(specifier || location!, runtimeImportSpecifier, errorMessage, location!);
const result = mod && mod !== unknownSymbol ? getMergedSymbol(resolveSymbol(mod)) : undefined;
if (links) {
Expand Down Expand Up @@ -49190,9 +49185,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
}
}

function resolveHelpersModule(node: SourceFile, errorNode: Node) {
function resolveHelpersModule(file: SourceFile, errorNode: Node) {
if (!externalHelpersModule) {
externalHelpersModule = resolveExternalModule(node, externalHelpersModuleNameText, Diagnostics.This_syntax_requires_an_imported_helper_but_module_0_cannot_be_found, errorNode) || unknownSymbol;
externalHelpersModule = resolveExternalModule(getImportHelpersImportSpecifier(file), externalHelpersModuleNameText, Diagnostics.This_syntax_requires_an_imported_helper_but_module_0_cannot_be_found, errorNode) || unknownSymbol;
}
return externalHelpersModule;
}
Expand Down Expand Up @@ -51142,6 +51137,23 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
blockScopeKind === NodeFlags.Using ||
blockScopeKind === NodeFlags.AwaitUsing;
}

function getJSXRuntimeImportSpecifier(file: SourceFile | undefined, specifierText: string) {
// Synthesized JSX import is either first or after tslib
const jsxImportIndex = compilerOptions.importHelpers ? 1 : 0;
const specifier = file?.imports[jsxImportIndex];
if (specifier) {
Debug.assert(nodeIsSynthesized(specifier) && specifier.text === specifierText, `Expected sourceFile.imports[${jsxImportIndex}] to be the synthesized JSX runtime import`);
}
return specifier;
}

function getImportHelpersImportSpecifier(file: SourceFile) {
Debug.assert(compilerOptions.importHelpers, "Expected importHelpers to be enabled");
const specifier = file.imports[0];
Debug.assert(specifier && nodeIsSynthesized(specifier) && specifier.text === "tslib", `Expected sourceFile.imports[0] to be the synthesized tslib import`);
return specifier;
}
}

function isNotAccessor(declaration: Declaration): boolean {
Expand Down
12 changes: 6 additions & 6 deletions src/compiler/program.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3365,7 +3365,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg

function createSyntheticImport(text: string, file: SourceFile) {
const externalHelpersModuleReference = factory.createStringLiteral(text);
const importDecl = factory.createImportDeclaration(/*modifiers*/ undefined, /*importClause*/ undefined, externalHelpersModuleReference, /*attributes*/ undefined);
const importDecl = factory.createImportDeclaration(/*modifiers*/ undefined, /*importClause*/ undefined, externalHelpersModuleReference);
addInternalEmitFlags(importDecl, InternalEmitFlags.NeverApplyImportHelper);
setParent(externalHelpersModuleReference, importDecl);
setParent(importDecl, file);
Expand All @@ -3390,11 +3390,11 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
let ambientModules: string[] | undefined;

// If we are importing helpers, we need to add a synthetic reference to resolve the
// helpers library.
if (
(getIsolatedModules(options) || isExternalModuleFile)
&& !file.isDeclarationFile
) {
// helpers library. (A JavaScript file without `externalModuleIndicator` set might be
// a CommonJS module; `commonJsModuleIndicator` doesn't get set until the binder has
// run. We synthesize a helpers import for it just in case; it will never be used if
// the binder doesn't find and set a `commonJsModuleIndicator`.)
if (isJavaScriptFile || (!file.isDeclarationFile && (getIsolatedModules(options) || isExternalModule(file)))) {
if (options.importHelpers) {
// synthesize 'import "tslib"' declaration
imports = [createSyntheticImport(externalHelpersModuleNameText, file)];
Expand Down
51 changes: 51 additions & 0 deletions tests/baselines/reference/importHelpersBundler.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
//// [tests/cases/compiler/importHelpersBundler.ts] ////

//// [package.json]
{
"name": "tslib",
"main": "tslib.js",
"module": "tslib.es6.js",
"jsnext:main": "tslib.es6.js",
"typings": "tslib.d.ts",
"exports": {
".": {
"module": {
"types": "./modules/index.d.ts",
"default": "./tslib.es6.mjs"
},
"import": {
"node": "./modules/index.js",
"default": {
"types": "./modules/index.d.ts",
"default": "./tslib.es6.mjs"
}
},
"default": "./tslib.js"
},
"./*": "./*",
"./": "./"
}
}

//// [tslib.d.ts]
export {};

//// [package.json]
{ "type": "module" }

//// [index.d.ts]
export declare var __rest: any;

//// [main.ts]
export function foo(args: any) {
const { bar, ...extraArgs } = args;
return extraArgs;
}


//// [main.js]
import { __rest } from "tslib";
export function foo(args) {
const { bar } = args, extraArgs = __rest(args, ["bar"]);
return extraArgs;
}
24 changes: 24 additions & 0 deletions tests/baselines/reference/importHelpersBundler.symbols
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
//// [tests/cases/compiler/importHelpersBundler.ts] ////

=== /node_modules/tslib/tslib.d.ts ===

export {};

=== /node_modules/tslib/modules/index.d.ts ===
export declare var __rest: any;
>__rest : Symbol(__rest, Decl(index.d.ts, 0, 18))

=== /main.ts ===
export function foo(args: any) {
>foo : Symbol(foo, Decl(main.ts, 0, 0))
>args : Symbol(args, Decl(main.ts, 0, 20))

const { bar, ...extraArgs } = args;
>bar : Symbol(bar, Decl(main.ts, 1, 9))
>extraArgs : Symbol(extraArgs, Decl(main.ts, 1, 14))
>args : Symbol(args, Decl(main.ts, 0, 20))

return extraArgs;
>extraArgs : Symbol(extraArgs, Decl(main.ts, 1, 14))
}

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

=== /node_modules/tslib/tslib.d.ts ===

export {};

=== /node_modules/tslib/modules/index.d.ts ===
export declare var __rest: any;
>__rest : any

=== /main.ts ===
export function foo(args: any) {
>foo : (args: any) => any
> : ^ ^^ ^^^^^^^^
>args : any

const { bar, ...extraArgs } = args;
>bar : any
> : ^^^
>extraArgs : any
> : ^^^
>args : any

return extraArgs;
>extraArgs : any
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
//// [tests/cases/compiler/importHelpersCommonJSJavaScript.ts] ////

//// [package.json]
{
"name": "tslib",
"main": "tslib.js",
"module": "tslib.es6.js",
"jsnext:main": "tslib.es6.js",
"typings": "tslib.d.ts",
"exports": {
".": {
"module": {
"types": "./modules/index.d.ts",
"default": "./tslib.es6.mjs"
},
"import": {
"node": "./modules/index.js",
"default": {
"types": "./modules/index.d.ts",
"default": "./tslib.es6.mjs"
}
},
"default": "./tslib.js"
},
"./*": "./*",
"./": "./"
}
}

//// [tslib.d.ts]
export declare var __extends: any;

//// [package.json]
{ "type": "module" }

//// [index.d.ts]
export {};

//// [index.js]
class Foo {}

class Bar extends Foo {}

module.exports = Bar;


//// [index.js]
var tslib_1 = require("tslib");
var Foo = /** @class */ (function () {
function Foo() {
}
return Foo;
}());
var Bar = /** @class */ (function (_super) {
tslib_1.__extends(Bar, _super);
function Bar() {
return _super !== null && _super.apply(this, arguments) || this;
}
return Bar;
}(Foo));
module.exports = Bar;
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
//// [tests/cases/compiler/importHelpersCommonJSJavaScript.ts] ////

=== /node_modules/tslib/tslib.d.ts ===
export declare var __extends: any;
>__extends : Symbol(__extends, Decl(tslib.d.ts, --, --))

=== /node_modules/tslib/modules/index.d.ts ===

export {};

=== /index.js ===
class Foo {}
>Foo : Symbol(Foo, Decl(index.js, 0, 0))

class Bar extends Foo {}
>Bar : Symbol(Bar, Decl(index.js, 0, 12))
>Foo : Symbol(Foo, Decl(index.js, 0, 0))

module.exports = Bar;
>module.exports : Symbol(module.exports, Decl(index.js, 0, 0))
>module : Symbol(export=, Decl(index.js, 2, 24))
>exports : Symbol(export=, Decl(index.js, 2, 24))
>Bar : Symbol(Bar, Decl(index.js, 0, 12))

Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
//// [tests/cases/compiler/importHelpersCommonJSJavaScript.ts] ////

=== /node_modules/tslib/tslib.d.ts ===
export declare var __extends: any;
>__extends : any

=== /node_modules/tslib/modules/index.d.ts ===

export {};

=== /index.js ===
class Foo {}
>Foo : Foo
> : ^^^

class Bar extends Foo {}
>Bar : Bar
> : ^^^
>Foo : Foo
> : ^^^

module.exports = Bar;
>module.exports = Bar : typeof Bar
> : ^^^^^^^^^^
>module.exports : typeof Bar
> : ^^^^^^^^^^
>module : { exports: typeof Bar; }
> : ^^^^^^^^^^^^^^^^^^^^^^^^
>exports : typeof Bar
> : ^^^^^^^^^^
>Bar : typeof Bar
> : ^^^^^^^^^^

Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
//// [tests/cases/compiler/importHelpersCommonJSJavaScript.ts] ////

//// [package.json]
{
"name": "tslib",
"main": "tslib.js",
"module": "tslib.es6.js",
"jsnext:main": "tslib.es6.js",
"typings": "tslib.d.ts",
"exports": {
".": {
"module": {
"types": "./modules/index.d.ts",
"default": "./tslib.es6.mjs"
},
"import": {
"node": "./modules/index.js",
"default": {
"types": "./modules/index.d.ts",
"default": "./tslib.es6.mjs"
}
},
"default": "./tslib.js"
},
"./*": "./*",
"./": "./"
}
}

//// [tslib.d.ts]
export declare var __extends: any;

//// [package.json]
{ "type": "module" }

//// [index.d.ts]
export {};

//// [index.js]
class Foo {}

class Bar extends Foo {}

module.exports = Bar;


//// [index.js]
var tslib_1 = require("tslib");
var Foo = /** @class */ (function () {
function Foo() {
}
return Foo;
}());
var Bar = /** @class */ (function (_super) {
tslib_1.__extends(Bar, _super);
function Bar() {
return _super !== null && _super.apply(this, arguments) || this;
}
return Bar;
}(Foo));
module.exports = Bar;
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
//// [tests/cases/compiler/importHelpersCommonJSJavaScript.ts] ////

=== /node_modules/tslib/tslib.d.ts ===
export declare var __extends: any;
>__extends : Symbol(__extends, Decl(tslib.d.ts, --, --))

=== /node_modules/tslib/modules/index.d.ts ===

export {};

=== /index.js ===
class Foo {}
>Foo : Symbol(Foo, Decl(index.js, 0, 0))

class Bar extends Foo {}
>Bar : Symbol(Bar, Decl(index.js, 0, 12))
>Foo : Symbol(Foo, Decl(index.js, 0, 0))

module.exports = Bar;
>module.exports : Symbol(module.exports, Decl(index.js, 0, 0))
>module : Symbol(export=, Decl(index.js, 2, 24))
>exports : Symbol(export=, Decl(index.js, 2, 24))
>Bar : Symbol(Bar, Decl(index.js, 0, 12))

Loading