Skip to content

Commit

Permalink
Pass correct useDefineForClassFields, derived from tsconfig
Browse files Browse the repository at this point in the history
  • Loading branch information
cspotcode committed Sep 14, 2023
1 parent a045c4e commit 487fe92
Show file tree
Hide file tree
Showing 3 changed files with 142 additions and 0 deletions.
113 changes: 113 additions & 0 deletions src/test/transpilers.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,4 +139,117 @@ test.suite('swc', (test) => {
`
);
});

test.suite('useDefineForClassFields', (test) => {
const input = outdent`
class Foo {
bar = 1;
}
`;
const outputNative = outdent`
let Foo = class Foo {
bar = 1;
};
`;
const outputCtorAssignment = outdent`
let Foo = class Foo {
constructor(){
this.bar = 1;
}
};
`;
const outputDefine = outdent`
function _define_property(obj, key, value) {
if (key in obj) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
} else {
obj[key] = value;
}
return obj;
}
let Foo = class Foo {
constructor(){
_define_property(this, "bar", 1);
}
};
`;
test(
'useDefineForClassFields unset, should default to true and emit native property assignment b/c `next` target',
compileMacro,
{
target: 'ESNext',
},
input,
outputNative
);
test(
'useDefineForClassFields unset, should default to true and emit native property assignment b/c new target',
compileMacro,
{
target: 'ES2022',
},
input,
outputNative
);
test(
'useDefineForClassFields unset, should default to false b/c old target',
compileMacro,
{
target: 'ES2021',
},
input,
outputCtorAssignment
);
test(
'useDefineForClassFields unset, should default to false b/c no target',
compileMacro,
{},
input,
outputCtorAssignment
);
test(
'useDefineForClassFields=true, should emit native property assignment b/c new target',
compileMacro,
{
useDefineForClassFields: true,
target: 'ES2022',
},
input,
outputNative
);
test(
'useDefineForClassFields=true, should emit define b/c old target',
compileMacro,
{
useDefineForClassFields: true,
target: 'ES2021',
},
input,
outputDefine
);
test(
'useDefineForClassFields=false, new target, should still emit legacy property assignment in ctor',
compileMacro,
{
useDefineForClassFields: false,
target: 'ES2022',
},
input,
outputCtorAssignment
);
test(
'useDefineForClassFields=false, old target, should emit legacy property assignment in ctor',
compileMacro,
{
useDefineForClassFields: false,
},
input,
outputCtorAssignment
);
});
});
4 changes: 4 additions & 0 deletions src/transpilers/swc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import type * as swcWasm from '@swc/wasm';
import type * as swcTypes from '@swc/core';
import type { CreateTranspilerOptions, Transpiler } from './types';
import type { NodeModuleEmitKind } from '..';
import { getUseDefineForClassFields } from '../ts-internals';

type SwcInstance = typeof swcTypes;
export interface SwcTranspilerOptions extends CreateTranspilerOptions {
Expand Down Expand Up @@ -194,6 +195,8 @@ export function createSwcOptions(
jsx === JsxEmit.ReactJSX || jsx === JsxEmit.ReactJSXDev ? 'automatic' : undefined;
const jsxDevelopment: swcTypes.ReactConfig['development'] = jsx === JsxEmit.ReactJSXDev ? true : undefined;

const useDefineForClassFields = getUseDefineForClassFields(compilerOptions);

const nonTsxOptions = createVariant(false);
const tsxOptions = createVariant(true);
return { nonTsxOptions, tsxOptions };
Expand Down Expand Up @@ -233,6 +236,7 @@ export function createSwcOptions(
pragmaFrag: jsxFragmentFactory!,
runtime: jsxRuntime,
},
useDefineForClassFields,
},
keepClassNames,
experimental: {
Expand Down
25 changes: 25 additions & 0 deletions src/ts-internals.ts
Original file line number Diff line number Diff line change
Expand Up @@ -329,3 +329,28 @@ function replaceWildcardCharacter(match: string, singleAsteriskRegexFragment: st
function isImplicitGlob(lastPathComponent: string): boolean {
return !/[.*?]/.test(lastPathComponent);
}

const ts_ScriptTarget_ES5 = 1;
const ts_ScriptTarget_ES2022 = 9;
const ts_ScriptTarget_ESNext = 99;
const ts_ModuleKind_Node16 = 100;
const ts_ModuleKind_NodeNext = 199;
// https://github.com/microsoft/TypeScript/blob/fc418a2e611c88cf9afa0115ff73490b2397d311/src/compiler/utilities.ts#L8761
export function getUseDefineForClassFields(compilerOptions: _ts.CompilerOptions): boolean {
return compilerOptions.useDefineForClassFields === undefined
? getEmitScriptTarget(compilerOptions) >= ts_ScriptTarget_ES2022
: compilerOptions.useDefineForClassFields;
}

// https://github.com/microsoft/TypeScript/blob/fc418a2e611c88cf9afa0115ff73490b2397d311/src/compiler/utilities.ts#L8556
export function getEmitScriptTarget(compilerOptions: {
module?: _ts.CompilerOptions['module'];
target?: _ts.CompilerOptions['target'];
}): _ts.ScriptTarget {
return (
compilerOptions.target ??
((compilerOptions.module === ts_ModuleKind_Node16 && ts_ScriptTarget_ES2022) ||
(compilerOptions.module === ts_ModuleKind_NodeNext && ts_ScriptTarget_ESNext) ||
ts_ScriptTarget_ES5)
);
}

0 comments on commit 487fe92

Please sign in to comment.