Skip to content

Commit bc50c75

Browse files
committed
Add --module preserve
1 parent 2c71621 commit bc50c75

File tree

13 files changed

+128
-21
lines changed

13 files changed

+128
-21
lines changed

src/compiler/checker.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45849,7 +45849,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
4584945849
}
4585045850
}
4585145851
else {
45852-
if (moduleKind >= ModuleKind.ES2015 && getSourceFileOfNode(node).impliedNodeFormat === undefined && !node.isTypeOnly && !(node.flags & NodeFlags.Ambient)) {
45852+
if (moduleKind >= ModuleKind.ES2015 && moduleKind !== ModuleKind.Preserve && getSourceFileOfNode(node).impliedNodeFormat === undefined && !node.isTypeOnly && !(node.flags & NodeFlags.Ambient)) {
4585345853
// Import equals declaration is deprecated in es6 or above
4585445854
grammarErrorOnNode(node, Diagnostics.Import_assignment_cannot_be_used_when_targeting_ECMAScript_modules_Consider_using_import_Asterisk_as_ns_from_mod_import_a_from_mod_import_d_from_mod_or_another_module_format_instead);
4585545855
}
@@ -46135,6 +46135,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
4613546135
// Forbid export= in esm implementation files, and esm mode declaration files
4613646136
if (
4613746137
moduleKind >= ModuleKind.ES2015 &&
46138+
moduleKind !== ModuleKind.Preserve &&
4613846139
((node.flags & NodeFlags.Ambient && getSourceFileOfNode(node).impliedNodeFormat === ModuleKind.ESNext) ||
4613946140
(!(node.flags & NodeFlags.Ambient) && getSourceFileOfNode(node).impliedNodeFormat !== ModuleKind.CommonJS))
4614046141
) {

src/compiler/commandLineParser.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -556,6 +556,7 @@ export const moduleOptionDeclaration: CommandLineOptionOfCustomType = {
556556
esnext: ModuleKind.ESNext,
557557
node16: ModuleKind.Node16,
558558
nodenext: ModuleKind.NodeNext,
559+
preserve: ModuleKind.Preserve,
559560
})),
560561
affectsSourceFile: true,
561562
affectsModuleResolution: true,

src/compiler/diagnosticMessages.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4293,7 +4293,7 @@
42934293
"category": "Error",
42944294
"code": 5070
42954295
},
4296-
"Option '--resolveJsonModule' can only be specified when module code generation is 'commonjs', 'amd', 'es2015' or 'esNext'.": {
4296+
"Option '--resolveJsonModule' cannot be specified when 'module' is set to 'none', 'system', or 'umd'.": {
42974297
"category": "Error",
42984298
"code": 5071
42994299
},
@@ -4385,7 +4385,7 @@
43854385
"category": "Error",
43864386
"code": 5094
43874387
},
4388-
"Option '{0}' can only be used when 'module' is set to 'es2015' or later.": {
4388+
"Option '{0}' can only be used when 'module' is set to 'preserve' or to 'es2015' or later.": {
43894389
"category": "Error",
43904390
"code": 5095
43914391
},

src/compiler/program.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4323,9 +4323,8 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
43234323
if (getEmitModuleResolutionKind(options) === ModuleResolutionKind.Classic) {
43244324
createDiagnosticForOptionName(Diagnostics.Option_resolveJsonModule_cannot_be_specified_when_moduleResolution_is_set_to_classic, "resolveJsonModule");
43254325
}
4326-
// Any emit other than common js, amd, es2015 or esnext is error
43274326
else if (!hasJsonModuleEmitEnabled(options)) {
4328-
createDiagnosticForOptionName(Diagnostics.Option_resolveJsonModule_can_only_be_specified_when_module_code_generation_is_commonjs_amd_es2015_or_esNext, "resolveJsonModule", "module");
4327+
createDiagnosticForOptionName(Diagnostics.Option_resolveJsonModule_cannot_be_specified_when_module_is_set_to_none_system_or_umd, "resolveJsonModule", "module");
43294328
}
43304329
}
43314330

@@ -4411,7 +4410,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
44114410
}
44124411

44134412
if (options.preserveValueImports && getEmitModuleKind(options) < ModuleKind.ES2015) {
4414-
createDiagnosticForOptionName(Diagnostics.Option_0_can_only_be_used_when_module_is_set_to_es2015_or_later, "preserveValueImports");
4413+
createDiagnosticForOptionName(Diagnostics.Option_0_can_only_be_used_when_module_is_set_to_preserve_or_to_es2015_or_later, "preserveValueImports");
44154414
}
44164415

44174416
const moduleKind = getEmitModuleKind(options);
@@ -4442,8 +4441,8 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
44424441
createDiagnosticForOptionName(Diagnostics.Option_0_can_only_be_used_when_moduleResolution_is_set_to_node16_nodenext_or_bundler, "customConditions");
44434442
}
44444443

4445-
if (moduleResolution === ModuleResolutionKind.Bundler && !emitModuleKindIsNonNodeESM(moduleKind)) {
4446-
createOptionValueDiagnostic("moduleResolution", Diagnostics.Option_0_can_only_be_used_when_module_is_set_to_es2015_or_later, "bundler");
4444+
if (moduleResolution === ModuleResolutionKind.Bundler && !emitModuleKindIsNonNodeESM(moduleKind) && moduleKind !== ModuleKind.Preserve) {
4445+
createOptionValueDiagnostic("moduleResolution", Diagnostics.Option_0_can_only_be_used_when_module_is_set_to_preserve_or_to_es2015_or_later, "bundler");
44474446
}
44484447

44494448
if (

src/compiler/transformer.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ function getModuleTransformer(moduleKind: ModuleKind): TransformerFactory<Source
8282
case ModuleKind.ES2022:
8383
case ModuleKind.ES2020:
8484
case ModuleKind.ES2015:
85+
case ModuleKind.Preserve:
8586
return transformECMAScriptModule;
8687
case ModuleKind.System:
8788
return transformSystemModule;

src/compiler/transformers/module/esnextAnd2015.ts

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import {
1111
ExportAssignment,
1212
ExportDeclaration,
1313
Expression,
14+
ExpressionStatement,
1415
GeneratedIdentifierFlags,
1516
getEmitFlags,
1617
getEmitModuleKind,
@@ -146,6 +147,9 @@ export function transformECMAScriptModule(context: TransformationContext): (x: S
146147
if (moduleName) {
147148
args.push(moduleName);
148149
}
150+
if (getEmitModuleKind(compilerOptions) === ModuleKind.Preserve) {
151+
return factory.createCallExpression(factory.createIdentifier("require"), /*typeArguments*/ undefined, args);
152+
}
149153

150154
if (!importRequireStatements) {
151155
const createRequireName = factory.createUniqueName("_createRequire", GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel);
@@ -238,9 +242,27 @@ export function transformECMAScriptModule(context: TransformationContext): (x: S
238242
return statements;
239243
}
240244

241-
function visitExportAssignment(node: ExportAssignment): VisitResult<ExportAssignment | undefined> {
242-
// Elide `export=` as it is not legal with --module ES6
243-
return node.isExportEquals ? undefined : node;
245+
function visitExportAssignment(node: ExportAssignment): VisitResult<ExportAssignment | ExpressionStatement | undefined> {
246+
if (node.isExportEquals) {
247+
if (getEmitModuleKind(compilerOptions) === ModuleKind.Preserve) {
248+
const statement = setOriginalNode(
249+
factory.createExpressionStatement(
250+
factory.createAssignment(
251+
factory.createPropertyAccessExpression(
252+
factory.createIdentifier("module"),
253+
"exports",
254+
),
255+
node.expression,
256+
),
257+
),
258+
node,
259+
);
260+
return statement;
261+
}
262+
// Elide `export=` as it is not legal with --module ES6
263+
return undefined;
264+
}
265+
return node;
244266
}
245267

246268
function visitExportDeclaration(node: ExportDeclaration) {

src/compiler/types.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7294,6 +7294,9 @@ export enum ModuleKind {
72947294
// Node16+ is an amalgam of commonjs (albeit updated) and es2022+, and represents a distinct module system from es2020/esnext
72957295
Node16 = 100,
72967296
NodeNext = 199,
7297+
7298+
// Emit as written
7299+
Preserve = 200,
72977300
}
72987301

72997302
export const enum JsxEmit {

src/compiler/utilities.ts

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8633,6 +8633,9 @@ export const computedOptions = createComputedCompilerOptions({
86338633
case ModuleKind.NodeNext:
86348634
moduleResolution = ModuleResolutionKind.NodeNext;
86358635
break;
8636+
case ModuleKind.Preserve:
8637+
moduleResolution = ModuleResolutionKind.Bundler;
8638+
break;
86368639
default:
86378640
moduleResolution = ModuleResolutionKind.Classic;
86388641
break;
@@ -8664,6 +8667,7 @@ export const computedOptions = createComputedCompilerOptions({
86648667
switch (computedOptions.module.computeValue(compilerOptions)) {
86658668
case ModuleKind.Node16:
86668669
case ModuleKind.NodeNext:
8670+
case ModuleKind.Preserve:
86678671
return true;
86688672
}
86698673
return false;
@@ -8856,18 +8860,12 @@ export function emitModuleKindIsNonNodeESM(moduleKind: ModuleKind) {
88568860
/** @internal */
88578861
export function hasJsonModuleEmitEnabled(options: CompilerOptions) {
88588862
switch (getEmitModuleKind(options)) {
8859-
case ModuleKind.CommonJS:
8860-
case ModuleKind.AMD:
8861-
case ModuleKind.ES2015:
8862-
case ModuleKind.ES2020:
8863-
case ModuleKind.ES2022:
8864-
case ModuleKind.ESNext:
8865-
case ModuleKind.Node16:
8866-
case ModuleKind.NodeNext:
8867-
return true;
8868-
default:
8863+
case ModuleKind.None:
8864+
case ModuleKind.System:
8865+
case ModuleKind.UMD:
88698866
return false;
88708867
}
8868+
return true;
88718869
}
88728870

88738871
/** @internal */

src/services/codefixes/importFixes.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1159,6 +1159,7 @@ function getUmdImportKind(importingFile: SourceFile, compilerOptions: CompilerOp
11591159
case ModuleKind.ES2022:
11601160
case ModuleKind.ESNext:
11611161
case ModuleKind.None:
1162+
case ModuleKind.Preserve:
11621163
// Fall back to the `import * as ns` style import.
11631164
return ImportKind.Namespace;
11641165
case ModuleKind.Node16:
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
//// [tests/cases/compiler/modulePreserve1.ts] ////
2+
3+
//// [a.ts]
4+
export class A {}
5+
6+
//// [b.ts]
7+
export = class B {}
8+
9+
//// [main.ts]
10+
import { A } from "./a";
11+
import B = require("./b");
12+
export { A, B };
13+
14+
15+
//// [a.js]
16+
export class A {
17+
}
18+
//// [b.js]
19+
module.exports = class B {
20+
};
21+
export {};
22+
//// [main.js]
23+
import { A } from "./a";
24+
const B = require("./b");
25+
export { A, B };

0 commit comments

Comments
 (0)