Skip to content

Commit 56b70da

Browse files
safarelicspotcode
andauthored
add Target ES2021 mapping in transpilers/swc (#1521)
* add Target ES2021 mapping in transpilers/swc I was getting error: `jsc.target should be es5 or upper to use getter / setter` and after investigation I've isolated issue and here is the "fix" * fix and add tests * fix * lintfix Co-authored-by: Andrew Bradley <[email protected]>
1 parent 8cde25b commit 56b70da

File tree

2 files changed

+83
-4
lines changed

2 files changed

+83
-4
lines changed

src/test/transpilers.spec.ts

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// third-party transpiler and swc transpiler tests
2+
// TODO: at the time of writing, other transpiler tests have not been moved into this file.
3+
// Should consolidate them here.
4+
5+
import { context } from './testlib';
6+
import { contextTsNodeUnderTest, testsDirRequire } from './helpers';
7+
import * as expect from 'expect';
8+
9+
const test = context(contextTsNodeUnderTest);
10+
11+
test.suite('swc', (test) => {
12+
test('verify that TS->SWC target mappings suppport all possible values from both TS and SWC', async (t) => {
13+
const swcTranspiler = testsDirRequire(
14+
'ts-node/transpilers/swc-experimental'
15+
) as typeof import('../transpilers/swc');
16+
17+
// Detect when mapping is missing any ts.ScriptTargets
18+
const ts = testsDirRequire('typescript') as typeof import('typescript');
19+
for (const key of Object.keys(ts.ScriptTarget)) {
20+
if (/^\d+$/.test(key)) continue;
21+
if (key === 'JSON') continue;
22+
expect(
23+
swcTranspiler.targetMapping.has(ts.ScriptTarget[key as any] as any)
24+
).toBe(true);
25+
}
26+
27+
// Detect when mapping is missing any swc targets
28+
// Assuming that tests/package.json declares @swc/core: latest
29+
const swc = testsDirRequire('@swc/core');
30+
let msg: string | undefined = undefined;
31+
try {
32+
swc.transformSync('', { jsc: { target: 'invalid' } });
33+
} catch (e) {
34+
msg = (e as Error).message;
35+
}
36+
expect(msg).toBeDefined();
37+
// Error looks like:
38+
// unknown variant `invalid`, expected one of `es3`, `es5`, `es2015`, `es2016`, `es2017`, `es2018`, `es2019`, `es2020`, `es2021` at line 1 column 28
39+
const match = msg!.match(/unknown variant.*, expected one of (.*) at line/);
40+
expect(match).toBeDefined();
41+
const targets = match![1].split(', ').map((v: string) => v.slice(1, -1));
42+
43+
for (const target of targets) {
44+
expect([...swcTranspiler.targetMapping.values()]).toContain(target);
45+
}
46+
});
47+
});

src/transpilers/swc.ts

+36-4
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,20 @@ export function create(createOptions: SwcTranspilerOptions): Transpiler {
5656
const nonTsxOptions = createSwcOptions(false);
5757
const tsxOptions = createSwcOptions(true);
5858
function createSwcOptions(isTsx: boolean): swcTypes.Options {
59-
const swcTarget = targetMapping.get(target!) ?? 'es3';
59+
let swcTarget = targetMapping.get(target!) ?? 'es3';
60+
// Downgrade to lower target if swc does not support the selected target.
61+
// Perhaps project has an older version of swc.
62+
// TODO cache the results of this; slightly faster
63+
let swcTargetIndex = swcTargets.indexOf(swcTarget);
64+
for (; swcTargetIndex >= 0; swcTargetIndex--) {
65+
try {
66+
swcInstance.transformSync('', {
67+
jsc: { target: swcTargets[swcTargetIndex] },
68+
});
69+
break;
70+
} catch (e) {}
71+
}
72+
swcTarget = swcTargets[swcTargetIndex];
6073
const keepClassNames = target! >= /* ts.ScriptTarget.ES2016 */ 3;
6174
const moduleType =
6275
module === ModuleKind.CommonJS
@@ -119,16 +132,35 @@ export function create(createOptions: SwcTranspilerOptions): Transpiler {
119132
};
120133
}
121134

122-
const targetMapping = new Map<ts.ScriptTarget, swcTypes.JscTarget>();
135+
/** @internal */
136+
export const targetMapping = new Map<ts.ScriptTarget, SwcTarget>();
123137
targetMapping.set(/* ts.ScriptTarget.ES3 */ 0, 'es3');
124138
targetMapping.set(/* ts.ScriptTarget.ES5 */ 1, 'es5');
125139
targetMapping.set(/* ts.ScriptTarget.ES2015 */ 2, 'es2015');
126140
targetMapping.set(/* ts.ScriptTarget.ES2016 */ 3, 'es2016');
127141
targetMapping.set(/* ts.ScriptTarget.ES2017 */ 4, 'es2017');
128142
targetMapping.set(/* ts.ScriptTarget.ES2018 */ 5, 'es2018');
129143
targetMapping.set(/* ts.ScriptTarget.ES2019 */ 6, 'es2019');
130-
targetMapping.set(/* ts.ScriptTarget.ES2020 */ 7, 'es2019');
131-
targetMapping.set(/* ts.ScriptTarget.ESNext */ 99, 'es2019');
144+
targetMapping.set(/* ts.ScriptTarget.ES2020 */ 7, 'es2020');
145+
targetMapping.set(/* ts.ScriptTarget.ES2021 */ 8, 'es2021');
146+
targetMapping.set(/* ts.ScriptTarget.ESNext */ 99, 'es2021');
147+
148+
type SwcTarget = typeof swcTargets[number];
149+
/**
150+
* @internal
151+
* We use this list to downgrade to a prior target when we probe swc to detect if it supports a particular target
152+
*/
153+
const swcTargets = [
154+
'es3',
155+
'es5',
156+
'es2015',
157+
'es2016',
158+
'es2017',
159+
'es2018',
160+
'es2019',
161+
'es2020',
162+
'es2021',
163+
] as const;
132164

133165
const ModuleKind = {
134166
None: 0,

0 commit comments

Comments
 (0)