Skip to content

Commit 08cdfb0

Browse files
committed
Backport swc fixes on main
1 parent 9639daa commit 08cdfb0

File tree

2 files changed

+60
-38
lines changed

2 files changed

+60
-38
lines changed

Diff for: src/transpilers/swc.ts

+35-38
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@ import type * as swcWasm from '@swc/wasm';
33
import type * as swcTypes from '@swc/core';
44
import type { CreateTranspilerOptions, Transpiler } from './types';
55
import type { NodeModuleEmitKind } from '..';
6+
import { getUseDefineForClassFields } from '../ts-internals';
67

7-
type SwcInstance = typeof swcWasm;
8+
type SwcInstance = typeof swcTypes;
89
export interface SwcTranspilerOptions extends CreateTranspilerOptions {
910
/**
1011
* swc compiler to use for compilation
@@ -28,10 +29,7 @@ export function create(createOptions: SwcTranspilerOptions): Transpiler {
2829
let swcDepName: string = 'swc';
2930
if (typeof swc === 'string') {
3031
swcDepName = swc;
31-
swcInstance = require(transpilerConfigLocalResolveHelper(
32-
swc,
33-
true
34-
)) as typeof swcWasm;
32+
swcInstance = require(transpilerConfigLocalResolveHelper(swc, true)) as SwcInstance;
3533
} else if (swc == null) {
3634
let swcResolved;
3735
try {
@@ -47,25 +45,17 @@ export function create(createOptions: SwcTranspilerOptions): Transpiler {
4745
);
4846
}
4947
}
50-
swcInstance = require(swcResolved) as typeof swcWasm;
48+
swcInstance = require(swcResolved) as SwcInstance;
5149
} else {
52-
swcInstance = swc;
50+
swcInstance = swc as any as SwcInstance;
5351
}
5452

5553
// Prepare SWC options derived from typescript compiler options
56-
const { nonTsxOptions, tsxOptions } = createSwcOptions(
57-
config.options,
58-
nodeModuleEmitKind,
59-
swcInstance,
60-
swcDepName
61-
);
54+
const { nonTsxOptions, tsxOptions } = createSwcOptions(config.options, nodeModuleEmitKind, swcInstance, swcDepName);
6255

6356
const transpile: Transpiler['transpile'] = (input, transpileOptions) => {
6457
const { fileName } = transpileOptions;
65-
const swcOptions =
66-
fileName.endsWith('.tsx') || fileName.endsWith('.jsx')
67-
? tsxOptions
68-
: nonTsxOptions;
58+
const swcOptions = fileName.endsWith('.tsx') || fileName.endsWith('.jsx') ? tsxOptions : nonTsxOptions;
6959
const { code, map } = swcInstance.transformSync(input, {
7060
...swcOptions,
7161
filename: fileName,
@@ -90,7 +80,7 @@ targetMapping.set(/* ts.ScriptTarget.ES2019 */ 6, 'es2019');
9080
targetMapping.set(/* ts.ScriptTarget.ES2020 */ 7, 'es2020');
9181
targetMapping.set(/* ts.ScriptTarget.ES2021 */ 8, 'es2021');
9282
targetMapping.set(/* ts.ScriptTarget.ES2022 */ 9, 'es2022');
93-
targetMapping.set(/* ts.ScriptTarget.ESNext */ 99, 'es2022');
83+
targetMapping.set(/* ts.ScriptTarget.ESNext */ 99, 'esnext');
9484

9585
type SwcTarget = typeof swcTargets[number];
9686
/**
@@ -108,6 +98,7 @@ const swcTargets = [
10898
'es2020',
10999
'es2021',
110100
'es2022',
101+
'esnext',
111102
] as const;
112103

113104
const ModuleKind = {
@@ -152,6 +143,7 @@ export function createSwcOptions(
152143
strict,
153144
alwaysStrict,
154145
noImplicitUseStrict,
146+
jsxImportSource,
155147
} = compilerOptions;
156148

157149
let swcTarget = targetMapping.get(target!) ?? 'es3';
@@ -162,15 +154,14 @@ export function createSwcOptions(
162154
for (; swcTargetIndex >= 0; swcTargetIndex--) {
163155
try {
164156
swcInstance.transformSync('', {
165-
jsc: { target: swcTargets[swcTargetIndex] },
157+
jsc: { target: swcTargets[swcTargetIndex] as swcWasm.JscTarget },
166158
});
167159
break;
168160
} catch (e) {}
169161
}
170162
swcTarget = swcTargets[swcTargetIndex];
171163
const keepClassNames = target! >= /* ts.ScriptTarget.ES2016 */ 3;
172-
const isNodeModuleKind =
173-
module === ModuleKind.Node16 || module === ModuleKind.NodeNext;
164+
const isNodeModuleKind = module === ModuleKind.Node16 || module === ModuleKind.NodeNext;
174165
// swc only supports these 4x module options [MUST_UPDATE_FOR_NEW_MODULEKIND]
175166
const moduleType =
176167
module === ModuleKind.CommonJS
@@ -202,11 +193,10 @@ export function createSwcOptions(
202193
: true;
203194

204195
const jsxRuntime: swcTypes.ReactConfig['runtime'] =
205-
jsx === JsxEmit.ReactJSX || jsx === JsxEmit.ReactJSXDev
206-
? 'automatic'
207-
: undefined;
208-
const jsxDevelopment: swcTypes.ReactConfig['development'] =
209-
jsx === JsxEmit.ReactJSXDev ? true : undefined;
196+
jsx === JsxEmit.ReactJSX || jsx === JsxEmit.ReactJSXDev ? 'automatic' : undefined;
197+
const jsxDevelopment: swcTypes.ReactConfig['development'] = jsx === JsxEmit.ReactJSXDev ? true : undefined;
198+
199+
const useDefineForClassFields = getUseDefineForClassFields(compilerOptions);
210200

211201
const nonTsxOptions = createVariant(false);
212202
const tsxOptions = createVariant(true);
@@ -217,13 +207,17 @@ export function createSwcOptions(
217207
sourceMaps: sourceMap,
218208
// isModule: true,
219209
module: moduleType
220-
? ({
221-
noInterop: !esModuleInterop,
210+
? {
222211
type: moduleType,
223-
strictMode,
224-
// For NodeNext and Node12, emit as CJS but do not transform dynamic imports
225-
ignoreDynamic: nodeModuleEmitKind === 'nodecjs',
226-
} as swcTypes.ModuleConfig)
212+
...(moduleType === 'amd' || moduleType === 'commonjs' || moduleType === 'umd'
213+
? {
214+
noInterop: !esModuleInterop,
215+
strictMode,
216+
// For NodeNext and Node12, emit as CJS but do not transform dynamic imports
217+
ignoreDynamic: nodeModuleEmitKind === 'nodecjs',
218+
}
219+
: {}),
220+
}
227221
: undefined,
228222
swcrc: false,
229223
jsc: {
@@ -234,8 +228,8 @@ export function createSwcOptions(
234228
decorators: experimentalDecorators,
235229
dynamicImport: true,
236230
importAssertions: true,
237-
},
238-
target: swcTarget,
231+
} as swcWasm.TsParserConfig,
232+
target: swcTarget as swcWasm.JscTarget,
239233
transform: {
240234
decoratorMetadata: emitDecoratorMetadata,
241235
legacyDecorator: true,
@@ -246,13 +240,16 @@ export function createSwcOptions(
246240
pragma: jsxFactory!,
247241
pragmaFrag: jsxFragmentFactory!,
248242
runtime: jsxRuntime,
249-
} as swcTypes.ReactConfig,
243+
importSource: jsxImportSource,
244+
},
245+
useDefineForClassFields,
250246
},
251247
keepClassNames,
252248
experimental: {
253-
keepImportAssertions: true,
254-
},
255-
} as swcTypes.JscConfig,
249+
keepImportAttributes: true,
250+
emitAssertForImportAttributes: true,
251+
} as swcTypes.JscConfig['experimental'],
252+
},
256253
};
257254

258255
// Throw a helpful error if swc version is old, for example, if it rejects `ignoreDynamic`

Diff for: src/ts-internals.ts

+25
Original file line numberDiff line numberDiff line change
@@ -399,3 +399,28 @@ function replaceWildcardCharacter(
399399
function isImplicitGlob(lastPathComponent: string): boolean {
400400
return !/[.*?]/.test(lastPathComponent);
401401
}
402+
403+
const ts_ScriptTarget_ES5 = 1;
404+
const ts_ScriptTarget_ES2022 = 9;
405+
const ts_ScriptTarget_ESNext = 99;
406+
const ts_ModuleKind_Node16 = 100;
407+
const ts_ModuleKind_NodeNext = 199;
408+
// https://github.com/microsoft/TypeScript/blob/fc418a2e611c88cf9afa0115ff73490b2397d311/src/compiler/utilities.ts#L8761
409+
export function getUseDefineForClassFields(compilerOptions: _ts.CompilerOptions): boolean {
410+
return compilerOptions.useDefineForClassFields === undefined
411+
? getEmitScriptTarget(compilerOptions) >= ts_ScriptTarget_ES2022
412+
: compilerOptions.useDefineForClassFields;
413+
}
414+
415+
// https://github.com/microsoft/TypeScript/blob/fc418a2e611c88cf9afa0115ff73490b2397d311/src/compiler/utilities.ts#L8556
416+
export function getEmitScriptTarget(compilerOptions: {
417+
module?: _ts.CompilerOptions['module'];
418+
target?: _ts.CompilerOptions['target'];
419+
}): _ts.ScriptTarget {
420+
return (
421+
compilerOptions.target ??
422+
((compilerOptions.module === ts_ModuleKind_Node16 && ts_ScriptTarget_ES2022) ||
423+
(compilerOptions.module === ts_ModuleKind_NodeNext && ts_ScriptTarget_ESNext) ||
424+
ts_ScriptTarget_ES5)
425+
);
426+
}

0 commit comments

Comments
 (0)