Skip to content

Commit 0bf051b

Browse files
committed
Rebase against master and clean up substitution flow
1 parent 2d77419 commit 0bf051b

File tree

84 files changed

+746
-693
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

84 files changed

+746
-693
lines changed

Diff for: src/compiler/transformers/module/module.ts

+102-49
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,24 @@
11
/*@internal*/
22
namespace ts {
3+
4+
const enum ImportOrExportBindingReferenceKind {
5+
None,
6+
ImportedHelper,
7+
TopLevelExportBinding,
8+
ImportClause,
9+
ImportSpecifier,
10+
}
11+
12+
type ImportOrExportBindingReferenceResult =
13+
| { kind: ImportOrExportBindingReferenceKind.None, node: undefined }
14+
| { kind: ImportOrExportBindingReferenceKind.ImportedHelper, node: Identifier }
15+
| { kind: ImportOrExportBindingReferenceKind.TopLevelExportBinding, node: undefined }
16+
| { kind: ImportOrExportBindingReferenceKind.ImportClause, node: ImportClause }
17+
| { kind: ImportOrExportBindingReferenceKind.ImportSpecifier, node: ImportSpecifier };
18+
19+
const noReferenceResult: ImportOrExportBindingReferenceResult = { kind: ImportOrExportBindingReferenceKind.None, node: undefined };
20+
const topLevelExportReferenceResult: ImportOrExportBindingReferenceResult = { kind: ImportOrExportBindingReferenceKind.TopLevelExportBinding, node: undefined };
21+
322
export function transformModule(context: TransformationContext) {
423
interface AsynchronousDependencies {
524
aliasedModuleNames: Expression[];
@@ -48,6 +67,7 @@ namespace ts {
4867
let currentModuleInfo: ExternalModuleInfo; // The ExternalModuleInfo for the current file.
4968
let noSubstitution: boolean[]; // Set of nodes for which substitution rules should be ignored.
5069
let needUMDDynamicImportHelper: boolean;
70+
let bindingReferenceCache: ESMap<Node, ImportOrExportBindingReferenceResult> | undefined;
5171

5272
return chainBundle(context, transformSourceFile);
5373

@@ -1756,24 +1776,70 @@ namespace ts {
17561776
return node;
17571777
}
17581778

1759-
function substituteCallExpression(node: CallExpression) {
1760-
if (!isIdentifier(node.expression)) {
1761-
return node;
1779+
function getImportOrExportBindingReferenceWorker(node: Identifier): ImportOrExportBindingReferenceResult {
1780+
if (getEmitFlags(node) & EmitFlags.HelperName) {
1781+
const externalHelpersModuleName = getExternalHelpersModuleName(currentSourceFile);
1782+
if (externalHelpersModuleName) {
1783+
return { kind: ImportOrExportBindingReferenceKind.ImportedHelper, node: externalHelpersModuleName };
1784+
}
17621785
}
1763-
const newExpression = substituteExpressionIdentifier(node.expression);
1764-
if (newExpression !== node.expression) {
1765-
return updateCall(node, setTextRange(createBinary(createNumericLiteral("0"), SyntaxKind.CommaToken, newExpression), node.expression), /*typeArguments*/ undefined, node.arguments);
1786+
else if (!(isGeneratedIdentifier(node) && !(node.autoGenerateFlags & GeneratedIdentifierFlags.AllowNameSubstitution)) && !isLocalName(node)) {
1787+
const exportContainer = resolver.getReferencedExportContainer(node, isExportName(node));
1788+
if (exportContainer?.kind === SyntaxKind.SourceFile) {
1789+
return topLevelExportReferenceResult;
1790+
}
1791+
const importDeclaration = resolver.getReferencedImportDeclaration(node);
1792+
if (importDeclaration) {
1793+
if (isImportClause(importDeclaration)) return { kind: ImportOrExportBindingReferenceKind.ImportClause, node: importDeclaration };
1794+
if (isImportSpecifier(importDeclaration)) return { kind: ImportOrExportBindingReferenceKind.ImportSpecifier, node: importDeclaration };
1795+
}
1796+
}
1797+
return noReferenceResult;
1798+
}
1799+
1800+
function getImportOrExportBindingReference(node: Identifier, removeEntry: boolean): ImportOrExportBindingReferenceResult {
1801+
bindingReferenceCache ||= new Map();
1802+
let result = bindingReferenceCache.get(node);
1803+
if (!result) {
1804+
result = getImportOrExportBindingReferenceWorker(node);
1805+
if (!removeEntry) {
1806+
switch (result.kind) {
1807+
case ImportOrExportBindingReferenceKind.ImportedHelper:
1808+
case ImportOrExportBindingReferenceKind.ImportClause:
1809+
case ImportOrExportBindingReferenceKind.ImportSpecifier:
1810+
bindingReferenceCache.set(node, result);
1811+
}
1812+
}
1813+
}
1814+
else if (removeEntry) {
1815+
bindingReferenceCache.delete(node);
1816+
}
1817+
return result;
1818+
}
1819+
1820+
function substituteCallExpression(node: CallExpression) {
1821+
if (isIdentifier(node.expression) && getImportOrExportBindingReference(node.expression, /*removeEntry*/ false).kind !== ImportOrExportBindingReferenceKind.None) {
1822+
return isCallChain(node) ?
1823+
factory.updateCallChain(node,
1824+
setTextRange(factory.createComma(factory.createNumericLiteral(0), node.expression), node.expression),
1825+
node.questionDotToken,
1826+
/*typeArguments*/ undefined,
1827+
node.arguments) :
1828+
factory.updateCallExpression(node,
1829+
setTextRange(factory.createComma(factory.createNumericLiteral(0), node.expression), node.expression),
1830+
/*typeArguments*/ undefined,
1831+
node.arguments);
17661832
}
17671833
return node;
17681834
}
17691835

17701836
function substituteTaggedTemplateExpression(node: TaggedTemplateExpression) {
1771-
if (!isIdentifier(node.tag)) {
1772-
return node;
1773-
}
1774-
const newTag = substituteExpressionIdentifier(node.tag);
1775-
if (newTag !== node.tag) {
1776-
return updateTaggedTemplate(node, setTextRange(createBinary(createNumericLiteral("0"), SyntaxKind.CommaToken, newTag), node.tag), /*typeArguments*/ undefined, node.template);
1837+
if (isIdentifier(node.tag) && getImportOrExportBindingReference(node.tag, /*removeEntry*/ false).kind !== ImportOrExportBindingReferenceKind.None) {
1838+
return factory.updateTaggedTemplateExpression(
1839+
node,
1840+
setTextRange(factory.createComma(factory.createNumericLiteral(0), node.tag), node.tag),
1841+
/*typeArguments*/ undefined,
1842+
node.template);
17771843
}
17781844
return node;
17791845
}
@@ -1785,51 +1851,38 @@ namespace ts {
17851851
* @param node The node to substitute.
17861852
*/
17871853
function substituteExpressionIdentifier(node: Identifier): Expression {
1788-
if (getEmitFlags(node) & EmitFlags.HelperName) {
1789-
const externalHelpersModuleName = getExternalHelpersModuleName(currentSourceFile);
1790-
if (externalHelpersModuleName) {
1791-
return factory.createPropertyAccessExpression(externalHelpersModuleName, node);
1792-
}
1793-
1794-
return node;
1795-
}
1796-
1797-
if (!(isGeneratedIdentifier(node) && !(node.autoGenerateFlags & GeneratedIdentifierFlags.AllowNameSubstitution)) && !isLocalName(node)) {
1798-
const exportContainer = resolver.getReferencedExportContainer(node, isExportName(node));
1799-
if (exportContainer && exportContainer.kind === SyntaxKind.SourceFile) {
1854+
const result = getImportOrExportBindingReference(node, /*removeEntry*/ true);
1855+
switch (result.kind) {
1856+
case ImportOrExportBindingReferenceKind.ImportedHelper:
1857+
return factory.createPropertyAccessExpression(result.node, node);
1858+
case ImportOrExportBindingReferenceKind.TopLevelExportBinding:
18001859
return setTextRange(
18011860
factory.createPropertyAccessExpression(
18021861
factory.createIdentifier("exports"),
18031862
factory.cloneNode(node)
18041863
),
18051864
/*location*/ node
18061865
);
1807-
}
1808-
1809-
const importDeclaration = resolver.getReferencedImportDeclaration(node);
1810-
if (importDeclaration) {
1811-
if (isImportClause(importDeclaration)) {
1812-
return setTextRange(
1813-
factory.createPropertyAccessExpression(
1814-
factory.getGeneratedNameForNode(importDeclaration.parent),
1815-
factory.createIdentifier("default")
1816-
),
1817-
/*location*/ node
1818-
);
1819-
}
1820-
else if (isImportSpecifier(importDeclaration)) {
1821-
const name = importDeclaration.propertyName || importDeclaration.name;
1822-
return setTextRange(
1823-
factory.createPropertyAccessExpression(
1824-
factory.getGeneratedNameForNode(importDeclaration.parent?.parent?.parent || importDeclaration),
1825-
factory.cloneNode(name)
1826-
),
1827-
/*location*/ node
1828-
);
1829-
}
1830-
}
1866+
case ImportOrExportBindingReferenceKind.ImportClause:
1867+
return setTextRange(
1868+
factory.createPropertyAccessExpression(
1869+
factory.getGeneratedNameForNode(result.node.parent),
1870+
factory.createIdentifier("default")
1871+
),
1872+
/*location*/ node
1873+
);
1874+
case ImportOrExportBindingReferenceKind.ImportSpecifier:
1875+
const name = result.node.propertyName || result.node.name;
1876+
return setTextRange(
1877+
factory.createPropertyAccessExpression(
1878+
factory.getGeneratedNameForNode(result.node.parent?.parent?.parent || result.node),
1879+
factory.cloneNode(name)
1880+
),
1881+
/*location*/ node
1882+
);
1883+
default:
1884+
return node;
18311885
}
1832-
return node;
18331886
}
18341887

18351888
/**

Diff for: tests/baselines/reference/commentsOnJSXExpressionsArePreserved(jsx=react-jsx,module=commonjs).js

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ var Component = /** @class */ (function () {
2525
function Component() {
2626
}
2727
Component.prototype.render = function () {
28-
return _a.jsx("div", { children: null /* preserved */ }, void 0);
28+
return (0, _a.jsx)("div", { children: null /* preserved */ }, void 0);
2929
};
3030
return Component;
3131
}());

Diff for: tests/baselines/reference/commentsOnJSXExpressionsArePreserved(jsx=react-jsxdev,module=commonjs).js

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ var Component = /** @class */ (function () {
2626
function Component() {
2727
}
2828
Component.prototype.render = function () {
29-
return _a.jsxDEV("div", { children: null /* preserved */ }, void 0, false, { fileName: _jsxFileName, lineNumber: 5, columnNumber: 15 }, this);
29+
return (0, _a.jsxDEV)("div", { children: null /* preserved */ }, void 0, false, { fileName: _jsxFileName, lineNumber: 5, columnNumber: 15 }, this);
3030
};
3131
return Component;
3232
}());

Diff for: tests/baselines/reference/declarationEmitExpandoWithGenericConstraint.js

+13-13
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
//// [declarationEmitExpandoWithGenericConstraint.ts]
2-
export interface Point {
3-
readonly x: number;
4-
readonly y: number;
5-
}
6-
7-
export interface Rect<p extends Point> {
8-
readonly a: p;
9-
readonly b: p;
10-
}
11-
12-
export const Point = (x: number, y: number): Point => ({ x, y });
13-
export const Rect = <p extends Point>(a: p, b: p): Rect<p> => ({ a, b });
14-
2+
export interface Point {
3+
readonly x: number;
4+
readonly y: number;
5+
}
6+
7+
export interface Rect<p extends Point> {
8+
readonly a: p;
9+
readonly b: p;
10+
}
11+
12+
export const Point = (x: number, y: number): Point => ({ x, y });
13+
export const Rect = <p extends Point>(a: p, b: p): Rect<p> => ({ a, b });
14+
1515
Point.zero = (): Point => Point(0, 0);
1616

1717
//// [declarationEmitExpandoWithGenericConstraint.js]

Diff for: tests/baselines/reference/declarationEmitExportAssignedNamespaceNoTripleSlashTypesReference.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ var get_comp_1 = require("./get-comp");
5353
// this shouldn't need any triple-slash references - it should have a direct import to `react` and that's it
5454
// This issue (#35343) _only_ reproduces in the test harness when the file in question is in a subfolder
5555
exports.obj = {
56-
comp: get_comp_1.getComp()
56+
comp: (0, get_comp_1.getComp)()
5757
};
5858
//// [some-other-file.js]
5959
"use strict";

Diff for: tests/baselines/reference/declarationEmitExportDeclaration.js

+7-7
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
//// [tests/cases/compiler/declarationEmitExportDeclaration.ts] ////
22

33
//// [utils.ts]
4-
export function foo() { }
5-
export function bar() { }
6-
export interface Buzz { }
4+
export function foo() { }
5+
export function bar() { }
6+
export interface Buzz { }
77

88
//// [index.ts]
9-
import {foo, bar, Buzz} from "./utils";
10-
11-
foo();
12-
let obj: Buzz;
9+
import {foo, bar, Buzz} from "./utils";
10+
11+
foo();
12+
let obj: Buzz;
1313
export {bar};
1414

1515
//// [utils.js]

Diff for: tests/baselines/reference/declarationEmitForModuleImportingModuleAugmentationRetainsImport.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ var ParentThing = /** @class */ (function () {
3131
return ParentThing;
3232
}());
3333
exports.ParentThing = ParentThing;
34-
child1_1.child1(ParentThing.prototype);
34+
(0, child1_1.child1)(ParentThing.prototype);
3535
//// [child1.js]
3636
"use strict";
3737
exports.__esModule = true;

Diff for: tests/baselines/reference/declarationEmitReadonlyComputedProperty.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ var __assign = (this && this.__assign) || function () {
4848
exports.__esModule = true;
4949
exports.spread = void 0;
5050
var bug_1 = require("./bug");
51-
exports.spread = __assign({}, bug_1.createInstance());
51+
exports.spread = __assign({}, (0, bug_1.createInstance)());
5252

5353

5454
//// [bug.d.ts]

Diff for: tests/baselines/reference/declarationEmitSymlinkPaths.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3838
exports.NotificationScenario = void 0;
3939
var index_1 = require("search/lib/index");
4040
var NotificationAPIUtils_1 = require("../API/NotificationAPIUtils");
41-
exports.NotificationScenario = index_1.test(NotificationAPIUtils_1.getNotification);
41+
exports.NotificationScenario = (0, index_1.test)(NotificationAPIUtils_1.getNotification);
4242

4343

4444
//// [NotificationAPIUtils.d.ts]

Diff for: tests/baselines/reference/declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.js

+39-39
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,43 @@
11
//// [declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.ts]
2-
// Note that both of the following have an `any` in their return type from where we bottom out the type printout
3-
// for having too many instances of the same symbol nesting.
4-
5-
// Slightly simplified repro from https://github.com/microsoft/TypeScript/issues/30732 so it's easier to read and debug
6-
export type Key<U> = keyof U;
7-
export type Value<K extends Key<U>, U> = U[K];
8-
export const updateIfChanged = <T>(t: T) => {
9-
const reduce = <U>(u: U, update: (u: U) => T) => {
10-
const set = (newU: U) => Object.is(u, newU) ? t : update(newU);
11-
return Object.assign(
12-
<K extends Key<U>>(key: K) =>
13-
reduce<Value<K, U>>(u[key as keyof U] as Value<K, U>, (v: Value<K, U>) => {
14-
return update(Object.assign(Array.isArray(u) ? [] : {}, u, { [key]: v }));
15-
}),
16-
{ map: (updater: (u: U) => U) => set(updater(u)), set });
17-
};
18-
return reduce<T>(t, (t: T) => t);
19-
};
20-
21-
// example from https://github.com/microsoft/TypeScript/issues/31605
22-
23-
export const testRecFun = <T extends Object>(parent: T) => {
24-
return {
25-
result: parent,
26-
deeper: <U extends Object>(child: U) =>
27-
testRecFun<T & U>({ ...parent, ...child })
28-
};
29-
}
30-
31-
32-
let p1 = testRecFun({ one: '1' })
33-
void p1.result.one;
34-
let p2 = p1.deeper({ two: '2' })
35-
void p2.result.one;
36-
void p2.result.two;
37-
let p3 = p2.deeper({ three: '3' })
38-
void p3.result.one;
39-
void p3.result.two;
40-
void p3.result.three;
2+
// Note that both of the following have an `any` in their return type from where we bottom out the type printout
3+
// for having too many instances of the same symbol nesting.
4+
5+
// Slightly simplified repro from https://github.com/microsoft/TypeScript/issues/30732 so it's easier to read and debug
6+
export type Key<U> = keyof U;
7+
export type Value<K extends Key<U>, U> = U[K];
8+
export const updateIfChanged = <T>(t: T) => {
9+
const reduce = <U>(u: U, update: (u: U) => T) => {
10+
const set = (newU: U) => Object.is(u, newU) ? t : update(newU);
11+
return Object.assign(
12+
<K extends Key<U>>(key: K) =>
13+
reduce<Value<K, U>>(u[key as keyof U] as Value<K, U>, (v: Value<K, U>) => {
14+
return update(Object.assign(Array.isArray(u) ? [] : {}, u, { [key]: v }));
15+
}),
16+
{ map: (updater: (u: U) => U) => set(updater(u)), set });
17+
};
18+
return reduce<T>(t, (t: T) => t);
19+
};
20+
21+
// example from https://github.com/microsoft/TypeScript/issues/31605
22+
23+
export const testRecFun = <T extends Object>(parent: T) => {
24+
return {
25+
result: parent,
26+
deeper: <U extends Object>(child: U) =>
27+
testRecFun<T & U>({ ...parent, ...child })
28+
};
29+
}
30+
31+
32+
let p1 = testRecFun({ one: '1' })
33+
void p1.result.one;
34+
let p2 = p1.deeper({ two: '2' })
35+
void p2.result.one;
36+
void p2.result.two;
37+
let p3 = p2.deeper({ three: '3' })
38+
void p3.result.one;
39+
void p3.result.two;
40+
void p3.result.three;
4141

4242

4343
//// [declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.js]

Diff for: tests/baselines/reference/exportAsNamespace_missingEmitHelpers.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,4 @@ exports.__esModule = true;
1515
exports.__esModule = true;
1616
exports.ns = void 0;
1717
var tslib_1 = require("tslib");
18-
exports.ns = tslib_1.__importStar(require("./a")); // Error
18+
exports.ns = (0, tslib_1.__importStar)(require("./a")); // Error

Diff for: tests/baselines/reference/exportAssignmentOfExportNamespaceWithDefault.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,4 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
2828
Object.defineProperty(exports, "__esModule", { value: true });
2929
// https://github.com/microsoft/TypeScript/issues/39149
3030
const a_1 = __importDefault(require("a"));
31-
a_1.default();
31+
(0, a_1.default)();

0 commit comments

Comments
 (0)