Skip to content

Commit

Permalink
Rewrite rather than shim literal-argument require/import calls
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewbranch committed Sep 24, 2024
1 parent 35c6438 commit 4c9557c
Show file tree
Hide file tree
Showing 9 changed files with 105 additions and 31 deletions.
17 changes: 11 additions & 6 deletions src/compiler/transformers/module/esnextAnd2015.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ export function transformECMAScriptModule(context: TransformationContext): (x: S
context.enableSubstitution(SyntaxKind.Identifier);

const noSubstitution = new Set<NodeId>();
let importsAndRequiresToShim: CallExpression[] | undefined;
let importsAndRequiresToRewriteOrShim: CallExpression[] | undefined;
let helperNameSubstitutions: Map<string, Identifier> | undefined;
let currentSourceFile: SourceFile | undefined;
let importRequireStatements: [ImportDeclaration, VariableStatement] | undefined;
Expand All @@ -98,7 +98,7 @@ export function transformECMAScriptModule(context: TransformationContext): (x: S
if (compilerOptions.rewriteRelativeImportExtensions && (currentSourceFile.flags & NodeFlags.PossiblyContainsDynamicImport || isInJSFile(node))) {
forEachDynamicImportOrRequireCall(node, /*includeTypeSpaceImports*/ false, /*requireStringLiteralLikeArgument*/ false, node => {
if (!isStringLiteralLike(node.arguments[0]) || shouldRewriteModuleSpecifier(node.arguments[0].text, compilerOptions)) {
importsAndRequiresToShim = append(importsAndRequiresToShim, node);
importsAndRequiresToRewriteOrShim = append(importsAndRequiresToRewriteOrShim, node);
}
});
}
Expand Down Expand Up @@ -155,12 +155,12 @@ export function transformECMAScriptModule(context: TransformationContext): (x: S
case SyntaxKind.ImportDeclaration:
return visitImportDeclaration(node as ImportDeclaration);
case SyntaxKind.CallExpression:
if (node === importsAndRequiresToShim?.[0]) {
return visitImportOrRequireCall(importsAndRequiresToShim.shift()!);
if (node === importsAndRequiresToRewriteOrShim?.[0]) {
return visitImportOrRequireCall(importsAndRequiresToRewriteOrShim.shift()!);
}
break;
default:
if (importsAndRequiresToShim?.length && rangeContainsRange(node, importsAndRequiresToShim[0])) {
if (importsAndRequiresToRewriteOrShim?.length && rangeContainsRange(node, importsAndRequiresToRewriteOrShim[0])) {
return visitEachChild(node, visitor, context);
}
}
Expand Down Expand Up @@ -190,7 +190,12 @@ export function transformECMAScriptModule(context: TransformationContext): (x: S
node,
node.expression,
node.typeArguments,
[emitHelpers().createRewriteRelativeImportExtensionsHelper(node.arguments[0]), ...node.arguments.slice(1)],
[
isStringLiteralLike(node.arguments[0])
? rewriteModuleSpecifier(node.arguments[0], compilerOptions)
: emitHelpers().createRewriteRelativeImportExtensionsHelper(node.arguments[0]),
...node.arguments.slice(1),
],
);
}

Expand Down
30 changes: 17 additions & 13 deletions src/compiler/transformers/module/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ export function transformModule(context: TransformationContext): (x: SourceFile

let currentSourceFile: SourceFile; // The current file.
let currentModuleInfo: ExternalModuleInfo; // The ExternalModuleInfo for the current file.
let importsAndRequiresToShim: CallExpression[] | undefined;
let importsAndRequiresToRewriteOrShim: CallExpression[] | undefined;
const noSubstitution: boolean[] = []; // Set of nodes for which substitution rules should be ignored.
let needUMDDynamicImportHelper: boolean;

Expand All @@ -244,7 +244,7 @@ export function transformModule(context: TransformationContext): (x: SourceFile
if (compilerOptions.rewriteRelativeImportExtensions) {
forEachDynamicImportOrRequireCall(node, /*includeTypeSpaceImports*/ false, /*requireStringLiteralLikeArgument*/ false, node => {
if (!isStringLiteralLike(node.arguments[0]) || shouldRewriteModuleSpecifier(node.arguments[0].text, compilerOptions)) {
importsAndRequiresToShim = append(importsAndRequiresToShim, node);
importsAndRequiresToRewriteOrShim = append(importsAndRequiresToRewriteOrShim, node);
}
});
}
Expand Down Expand Up @@ -795,7 +795,7 @@ export function transformModule(context: TransformationContext): (x: SourceFile
function visitorWorker(node: Node, valueIsDiscarded: boolean): VisitResult<Node> {
// This visitor does not need to descend into the tree if there is no dynamic import, destructuring assignment, or update expression
// as export/import statements are only transformed at the top level of a file.
if (!(node.transformFlags & (TransformFlags.ContainsDynamicImport | TransformFlags.ContainsDestructuringAssignment | TransformFlags.ContainsUpdateExpressionForIdentifier)) && !importsAndRequiresToShim?.length) {
if (!(node.transformFlags & (TransformFlags.ContainsDynamicImport | TransformFlags.ContainsDestructuringAssignment | TransformFlags.ContainsUpdateExpressionForIdentifier)) && !importsAndRequiresToRewriteOrShim?.length) {
return node;
}

Expand All @@ -809,15 +809,15 @@ export function transformModule(context: TransformationContext): (x: SourceFile
case SyntaxKind.PartiallyEmittedExpression:
return visitPartiallyEmittedExpression(node as PartiallyEmittedExpression, valueIsDiscarded);
case SyntaxKind.CallExpression:
const needsShim = node === firstOrUndefined(importsAndRequiresToShim);
if (needsShim) {
importsAndRequiresToShim!.shift();
const needsRewrite = node === firstOrUndefined(importsAndRequiresToRewriteOrShim);
if (needsRewrite) {
importsAndRequiresToRewriteOrShim!.shift();
}
if (isImportCall(node) && host.shouldTransformImportCall(currentSourceFile)) {
return visitImportCallExpression(node, needsShim);
return visitImportCallExpression(node, needsRewrite);
}
else if (needsShim) {
return shimImportOrRequireCall(node as CallExpression);
else if (needsRewrite) {
return shimOrRewriteImportOrRequireCall(node as CallExpression);
}
break;
case SyntaxKind.BinaryExpression:
Expand Down Expand Up @@ -1189,21 +1189,23 @@ export function transformModule(context: TransformationContext): (x: SourceFile
return visitEachChild(node, visitor, context);
}

function shimImportOrRequireCall(node: CallExpression): CallExpression {
function shimOrRewriteImportOrRequireCall(node: CallExpression): CallExpression {
return factory.updateCallExpression(
node,
node.expression,
/*typeArguments*/ undefined,
visitNodes(node.arguments, (arg: Expression) => {
if (arg === node.arguments[0]) {
return emitHelpers().createRewriteRelativeImportExtensionsHelper(arg);
return isStringLiteralLike(arg)
? rewriteModuleSpecifier(arg, compilerOptions)
: emitHelpers().createRewriteRelativeImportExtensionsHelper(arg);
}
return visitor(arg);
}, isExpression),
);
}

function visitImportCallExpression(node: ImportCall, shim: boolean): Expression {
function visitImportCallExpression(node: ImportCall, rewriteOrShim: boolean): Expression {
if (moduleKind === ModuleKind.None && languageVersion >= ScriptTarget.ES2020) {
return visitEachChild(node, visitor, context);
}
Expand All @@ -1212,7 +1214,9 @@ export function transformModule(context: TransformationContext): (x: SourceFile
// Only use the external module name if it differs from the first argument. This allows us to preserve the quote style of the argument on output.
const argument = externalModuleName && (!firstArgument || !isStringLiteral(firstArgument) || firstArgument.text !== externalModuleName.text)
? externalModuleName
: firstArgument && shim ? emitHelpers().createRewriteRelativeImportExtensionsHelper(firstArgument) : firstArgument;
: firstArgument && rewriteOrShim
? isStringLiteral(firstArgument) ? rewriteModuleSpecifier(firstArgument, compilerOptions) : emitHelpers().createRewriteRelativeImportExtensionsHelper(firstArgument)
: firstArgument;
const containsLexicalThis = !!(node.transformFlags & TransformFlags.ContainsLexicalThis);
switch (compilerOptions.module) {
case ModuleKind.AMD:
Expand Down
12 changes: 6 additions & 6 deletions tests/baselines/reference/emit(jsx=preserve).js
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,8 @@ const foo = require("./foo.js");
import "./foo.js";
export * from "./foo.js";
//Shim
import(__rewriteRelativeImportExtension("./foo.ts", true));
import(__rewriteRelativeImportExtension("./foo.ts", true), { with: { attr: "value" } });
import("./foo.js");
import("./foo.js", { with: { attr: "value" } });
import(__rewriteRelativeImportExtension("" + "./foo.ts", true));
//// [js.js]
var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExtension) || function (path, preserveJsx) {
Expand All @@ -106,11 +106,11 @@ import {} from "./foo.jsx";
import "./foo.js";
export * from "./foo.js";
// Shim
import(__rewriteRelativeImportExtension("./foo.ts", true));
import(__rewriteRelativeImportExtension("./foo.ts", true), { with: { attr: "value" } });
require(__rewriteRelativeImportExtension("./foo.ts", true));
import("./foo.js");
import("./foo.js", { with: { attr: "value" } });
require("./foo.js");
{
require(__rewriteRelativeImportExtension("./foo.ts", true));
require("./foo.js");
require(__rewriteRelativeImportExtension(getPath(), true));
}
// No rewrite or shim
Expand Down
12 changes: 6 additions & 6 deletions tests/baselines/reference/emit(jsx=react).js
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,8 @@ const foo = require("./foo.js");
import "./foo.js";
export * from "./foo.js";
//Shim
import(__rewriteRelativeImportExtension("./foo.ts"));
import(__rewriteRelativeImportExtension("./foo.ts"), { with: { attr: "value" } });
import("./foo.js");
import("./foo.js", { with: { attr: "value" } });
import(__rewriteRelativeImportExtension("" + "./foo.ts"));
//// [js.js]
var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExtension) || function (path, preserveJsx) {
Expand All @@ -106,11 +106,11 @@ import {} from "./foo.js";
import "./foo.js";
export * from "./foo.js";
// Shim
import(__rewriteRelativeImportExtension("./foo.ts"));
import(__rewriteRelativeImportExtension("./foo.ts"), { with: { attr: "value" } });
require(__rewriteRelativeImportExtension("./foo.ts"));
import("./foo.js");
import("./foo.js", { with: { attr: "value" } });
require("./foo.js");
{
require(__rewriteRelativeImportExtension("./foo.ts"));
require("./foo.js");
require(__rewriteRelativeImportExtension(getPath()));
}
// No rewrite or shim
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
a.js(4,11): error TS2307: Cannot find module './foo.ts' or its corresponding type declarations.
a.js(5,10): error TS2307: Cannot find module './foo.ts' or its corresponding type declarations.
b.ts(3,10): error TS2307: Cannot find module './foo.ts' or its corresponding type declarations.


==== a.js (2 errors) ====
{
require("" + "./foo.ts");
import("" + "./foo.ts");
require("./foo.ts");
~~~~~~~~~~
!!! error TS2307: Cannot find module './foo.ts' or its corresponding type declarations.
import("./foo.ts");
~~~~~~~~~~
!!! error TS2307: Cannot find module './foo.ts' or its corresponding type declarations.
}

==== b.ts (1 errors) ====
{
import("" + "./foo.ts");
import("./foo.ts");
~~~~~~~~~~
!!! error TS2307: Cannot find module './foo.ts' or its corresponding type declarations.
}

Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,14 @@
{
require("" + "./foo.ts");
import("" + "./foo.ts");
require("./foo.ts");
import("./foo.ts");
}

//// [b.ts]
{
import("" + "./foo.ts");
import("./foo.ts");
}


Expand All @@ -32,6 +35,8 @@ var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExte
{
require(__rewriteRelativeImportExtension("" + "./foo.ts"));
Promise.resolve(`${__rewriteRelativeImportExtension("" + "./foo.ts")}`).then(s => require(s));
require("./foo.js");
Promise.resolve().then(() => require("./foo.js"));
}
//// [b.js]
var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExtension) || function (path, preserveJsx) {
Expand All @@ -52,4 +57,5 @@ var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExte
};
{
Promise.resolve(`${__rewriteRelativeImportExtension("" + "./foo.ts")}`).then(s => require(s));
Promise.resolve().then(() => require("./foo.js"));
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
a.js(4,11): error TS2307: Cannot find module './foo.ts' or its corresponding type declarations.
a.js(5,10): error TS2307: Cannot find module './foo.ts' or its corresponding type declarations.
b.ts(3,10): error TS2307: Cannot find module './foo.ts' or its corresponding type declarations.


==== a.js (2 errors) ====
{
require("" + "./foo.ts");
import("" + "./foo.ts");
require("./foo.ts");
~~~~~~~~~~
!!! error TS2307: Cannot find module './foo.ts' or its corresponding type declarations.
import("./foo.ts");
~~~~~~~~~~
!!! error TS2307: Cannot find module './foo.ts' or its corresponding type declarations.
}

==== b.ts (1 errors) ====
{
import("" + "./foo.ts");
import("./foo.ts");
~~~~~~~~~~
!!! error TS2307: Cannot find module './foo.ts' or its corresponding type declarations.
}

Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,14 @@
{
require("" + "./foo.ts");
import("" + "./foo.ts");
require("./foo.ts");
import("./foo.ts");
}

//// [b.ts]
{
import("" + "./foo.ts");
import("./foo.ts");
}


Expand All @@ -33,6 +36,8 @@ var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExte
{
require(__rewriteRelativeImportExtension("" + "./foo.ts"));
import(__rewriteRelativeImportExtension("" + "./foo.ts"));
require("./foo.js");
import("./foo.js");
}
//// [b.js]
"use strict";
Expand All @@ -55,4 +60,5 @@ var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExte
Object.defineProperty(exports, "__esModule", { value: true });
{
import(__rewriteRelativeImportExtension("" + "./foo.ts"));
import("./foo.js");
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,12 @@
{
require("" + "./foo.ts");
import("" + "./foo.ts");
require("./foo.ts");
import("./foo.ts");
}

// @Filename: b.ts
{
import("" + "./foo.ts");
import("./foo.ts");
}

0 comments on commit 4c9557c

Please sign in to comment.