Skip to content

Revert #35877 - fix receiver on calls of imported and exported functions #43993

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
May 7, 2021
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
141 changes: 32 additions & 109 deletions src/compiler/transformers/module/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,6 @@ namespace ts {
context.onEmitNode = onEmitNode;
context.enableSubstitution(SyntaxKind.Identifier); // Substitutes expression identifiers with imported/exported symbols.
context.enableSubstitution(SyntaxKind.BinaryExpression); // Substitutes assignments to exported symbols.
context.enableSubstitution(SyntaxKind.CallExpression); // Substitutes expression identifiers with imported/exported symbols.
context.enableSubstitution(SyntaxKind.TaggedTemplateExpression); // Substitutes expression identifiers with imported/exported symbols.
context.enableSubstitution(SyntaxKind.PrefixUnaryExpression); // Substitutes updates to exported symbols.
context.enableSubstitution(SyntaxKind.PostfixUnaryExpression); // Substitutes updates to exported symbols.
context.enableSubstitution(SyntaxKind.ShorthandPropertyAssignment); // Substitutes shorthand property assignments for imported/exported symbols.
Expand All @@ -49,7 +47,6 @@ namespace ts {
let currentModuleInfo: ExternalModuleInfo; // The ExternalModuleInfo for the current file.
let noSubstitution: boolean[]; // Set of nodes for which substitution rules should be ignored.
let needUMDDynamicImportHelper: boolean;
let bindingReferenceCache: ESMap<Node, Identifier | SourceFile | ImportClause | ImportSpecifier | undefined> | undefined;

return chainBundle(context, transformSourceFile);

Expand Down Expand Up @@ -1746,10 +1743,6 @@ namespace ts {
return substituteExpressionIdentifier(<Identifier>node);
case SyntaxKind.BinaryExpression:
return substituteBinaryExpression(<BinaryExpression>node);
case SyntaxKind.CallExpression:
return substituteCallExpression(<CallExpression>node);
case SyntaxKind.TaggedTemplateExpression:
return substituteTaggedTemplateExpression(<TaggedTemplateExpression>node);
case SyntaxKind.PostfixUnaryExpression:
case SyntaxKind.PrefixUnaryExpression:
return substituteUnaryExpression(<PrefixUnaryExpression | PostfixUnaryExpression>node);
Expand All @@ -1759,124 +1752,54 @@ namespace ts {
}

/**
* For an Identifier, gets the import or export binding that it references.
* @returns One of the following:
* - An `Identifier` if node references an external helpers module (i.e., `tslib`).
* - A `SourceFile` if the node references an export in the file.
* - An `ImportClause` or `ImportSpecifier` if the node references an import binding.
* - Otherwise, `undefined`.
* Substitution for an Identifier expression that may contain an imported or exported
* symbol.
*
* @param node The node to substitute.
*/
function getImportOrExportBindingReferenceWorker(node: Identifier): Identifier | SourceFile | ImportClause | ImportSpecifier | undefined {
function substituteExpressionIdentifier(node: Identifier): Expression {
if (getEmitFlags(node) & EmitFlags.HelperName) {
const externalHelpersModuleName = getExternalHelpersModuleName(currentSourceFile);
if (externalHelpersModuleName) {
return externalHelpersModuleName;
return factory.createPropertyAccessExpression(externalHelpersModuleName, node);
}
return node;
}
else if (!(isGeneratedIdentifier(node) && !(node.autoGenerateFlags & GeneratedIdentifierFlags.AllowNameSubstitution)) && !isLocalName(node)) {
const exportContainer = resolver.getReferencedExportContainer(node, isExportName(node));
if (exportContainer?.kind === SyntaxKind.SourceFile) {
return exportContainer;
}
const importDeclaration = resolver.getReferencedImportDeclaration(node);
if (importDeclaration && (isImportClause(importDeclaration) || isImportSpecifier(importDeclaration))) {
return importDeclaration;
}
}
return undefined;
}

/**
* For an Identifier, gets the import or export binding that it references.
* @param removeEntry When `false`, the result is cached to avoid recomputing the result in a later substitution.
* When `true`, any cached result for the node is removed.
* @returns One of the following:
* - An `Identifier` if node references an external helpers module (i.e., `tslib`).
* - A `SourceFile` if the node references an export in the file.
* - An `ImportClause` or `ImportSpecifier` if the node references an import binding.
* - Otherwise, `undefined`.
*/
function getImportOrExportBindingReference(node: Identifier, removeEntry: boolean): Identifier | SourceFile | ImportClause | ImportSpecifier | undefined {
let result = bindingReferenceCache?.get(node);
if (!result && !bindingReferenceCache?.has(node)) {
result = getImportOrExportBindingReferenceWorker(node);
if (!removeEntry) {
bindingReferenceCache ||= new Map();
bindingReferenceCache.set(node, result);
}
}
else if (removeEntry) {
bindingReferenceCache?.delete(node);
}
return result;
}

function substituteCallExpression(node: CallExpression) {
if (isIdentifier(node.expression) && getImportOrExportBindingReference(node.expression, /*removeEntry*/ false)) {
return isCallChain(node) ?
factory.updateCallChain(node,
setTextRange(factory.createComma(factory.createNumericLiteral(0), node.expression), node.expression),
node.questionDotToken,
/*typeArguments*/ undefined,
node.arguments) :
factory.updateCallExpression(node,
setTextRange(factory.createComma(factory.createNumericLiteral(0), node.expression), node.expression),
/*typeArguments*/ undefined,
node.arguments);
}
return node;
}

function substituteTaggedTemplateExpression(node: TaggedTemplateExpression) {
if (isIdentifier(node.tag) && getImportOrExportBindingReference(node.tag, /*removeEntry*/ false)) {
return factory.updateTaggedTemplateExpression(
node,
setTextRange(factory.createComma(factory.createNumericLiteral(0), node.tag), node.tag),
/*typeArguments*/ undefined,
node.template);
}
return node;
}

/**
* Substitution for an Identifier expression that may contain an imported or exported
* symbol.
*
* @param node The node to substitute.
*/
function substituteExpressionIdentifier(node: Identifier): Expression {
const result = getImportOrExportBindingReference(node, /*removeEntry*/ true);
switch (result?.kind) {
case SyntaxKind.Identifier: // tslib import
return factory.createPropertyAccessExpression(result, node);
case SyntaxKind.SourceFile: // top-level export
if (exportContainer && exportContainer.kind === SyntaxKind.SourceFile) {
return setTextRange(
factory.createPropertyAccessExpression(
factory.createIdentifier("exports"),
factory.cloneNode(node)
),
/*location*/ node
);
case SyntaxKind.ImportClause:
return setTextRange(
factory.createPropertyAccessExpression(
factory.getGeneratedNameForNode(result.parent),
factory.createIdentifier("default")
),
/*location*/ node
);
case SyntaxKind.ImportSpecifier:
const name = result.propertyName || result.name;
return setTextRange(
factory.createPropertyAccessExpression(
factory.getGeneratedNameForNode(result.parent?.parent?.parent || result),
factory.cloneNode(name)
),
/*location*/ node
);
default:
return node;
}
const importDeclaration = resolver.getReferencedImportDeclaration(node);
if (importDeclaration) {
if (isImportClause(importDeclaration)) {
return setTextRange(
factory.createPropertyAccessExpression(
factory.getGeneratedNameForNode(importDeclaration.parent),
factory.createIdentifier("default")
),
/*location*/ node
);
}
else if (isImportSpecifier(importDeclaration)) {
const name = importDeclaration.propertyName || importDeclaration.name;
return setTextRange(
factory.createPropertyAccessExpression(
factory.getGeneratedNameForNode(importDeclaration.parent?.parent?.parent || importDeclaration),
factory.cloneNode(name)
),
/*location*/ node
);
}
}
}
return node;
}

/**
Expand Down
1 change: 0 additions & 1 deletion src/testRunner/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,6 @@
"unittests/evaluation/asyncGenerator.ts",
"unittests/evaluation/awaiter.ts",
"unittests/evaluation/destructuring.ts",
"unittests/evaluation/externalModules.ts",
"unittests/evaluation/forAwaitOf.ts",
"unittests/evaluation/forOf.ts",
"unittests/evaluation/optionalCall.ts",
Expand Down
84 changes: 0 additions & 84 deletions src/testRunner/unittests/evaluation/externalModules.ts

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@ exports.fn3 = fn3;`;
content: `"use strict";
exports.__esModule = true;${appendJsText === changeJs ? "\nexports.fn3 = void 0;" : ""}
var fns_1 = require("../decls/fns");
(0, fns_1.fn1)();
(0, fns_1.fn2)();
fns_1.fn1();
fns_1.fn2();
${appendJs}`
}];
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ exports.__esModule = true;
exports.a = void 0;
var func_1 = require("./func");
// hover on vextend
exports.a = (0, func_1.vextend)({
exports.a = func_1.vextend({
watch: {
data1: function (val) {
this.data2 = 1;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ exports.__esModule = true;
exports.__esModule = true;
exports.A = void 0;
var file1_1 = require("./file1");
exports.A = (0, file1_1.styled)();
exports.A = file1_1.styled();


//// [color.d.ts]
Expand Down
6 changes: 3 additions & 3 deletions tests/baselines/reference/ambientDeclarationsPatterns.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@ foo(fileText);
exports.__esModule = true;
///<reference path="declarations.d.ts" />
var foobarbaz_1 = require("foobarbaz");
(0, foobarbaz_1.foo)(foobarbaz_1.baz);
foobarbaz_1.foo(foobarbaz_1.baz);
var foosball_1 = require("foosball");
(0, foobarbaz_1.foo)(foosball_1.foos);
foobarbaz_1.foo(foosball_1.foos);
// Works with relative file name
var file_text_1 = require("./file!text");
(0, foobarbaz_1.foo)(file_text_1["default"]);
foobarbaz_1.foo(file_text_1["default"]);
2 changes: 1 addition & 1 deletion tests/baselines/reference/ambientShorthand.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,4 @@ exports.__esModule = true;
var jquery_1 = require("jquery");
var baz = require("fs");
var boom = require("jquery");
(0, jquery_1["default"])(jquery_1.bar, baz, boom);
jquery_1["default"](jquery_1.bar, baz, boom);
2 changes: 1 addition & 1 deletion tests/baselines/reference/ambientShorthand_reExport.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,4 @@ exports.__esModule = true;
var reExportX_1 = require("./reExportX");
var $ = require("./reExportAll");
// '$' is not callable, it is an object.
(0, reExportX_1.x)($);
reExportX_1.x($);
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ define("Class", ["require", "exports", "Configurable"], function (require, expor
return _super !== null && _super.apply(this, arguments) || this;
}
return ActualClass;
}((0, Configurable_1.Configurable)(HiddenClass)));
}(Configurable_1.Configurable(HiddenClass)));
exports.ActualClass = ActualClass;
});

Expand Down
4 changes: 2 additions & 2 deletions tests/baselines/reference/anonClassDeclarationEmitIsAnon.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ var __extends = (this && this.__extends) || (function () {
exports.__esModule = true;
exports.TimestampedUser = exports.User = void 0;
var wrapClass_1 = require("./wrapClass");
exports["default"] = (0, wrapClass_1.wrapClass)(0);
exports["default"] = wrapClass_1.wrapClass(0);
// Simple class
var User = /** @class */ (function () {
function User() {
Expand All @@ -112,7 +112,7 @@ var TimestampedUser = /** @class */ (function (_super) {
return _super.call(this) || this;
}
return TimestampedUser;
}((0, wrapClass_1.Timestamped)(User)));
}(wrapClass_1.Timestamped(User)));
exports.TimestampedUser = TimestampedUser;


Expand Down
2 changes: 1 addition & 1 deletion tests/baselines/reference/callbackTagVariadicType.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ exports.x = void 0;
/** @type {Foo} */
var x = function () { return 1; };
exports.x = x;
var res = (0, exports.x)('a', 'b');
var res = exports.x('a', 'b');


//// [callbackTagVariadicType.d.ts]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ var Component = /** @class */ (function () {
function Component() {
}
Component.prototype.render = function () {
return (0, _a.jsx)("div", { children: null /* preserved */ }, void 0);
return _a.jsx("div", { children: null /* preserved */ }, void 0);
};
return Component;
}());
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ var Component = /** @class */ (function () {
function Component() {
}
Component.prototype.render = function () {
return (0, _a.jsxDEV)("div", { children: null /* preserved */ }, void 0, false, { fileName: _jsxFileName, lineNumber: 5, columnNumber: 15 }, this);
return _a.jsxDEV("div", { children: null /* preserved */ }, void 0, false, { fileName: _jsxFileName, lineNumber: 5, columnNumber: 15 }, this);
};
return Component;
}());
2 changes: 1 addition & 1 deletion tests/baselines/reference/commonjsSafeImport.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ exports.Foo = Foo;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var _10_lib_1 = require("./10_lib");
(0, _10_lib_1.Foo)();
_10_lib_1.Foo();


//// [10_lib.d.ts]
Expand Down
Loading