Changelog: swc v1.2.52


external helper: typeof (#1557, #1458)#

Previously swc used incorrect name for typeof helpers, if extenalHelpers is true.

"jsc": {
"externalHelpers": true,
"target": "es2015"

This is now fixed.

helper bugs (#1555)#

Some helpers were compiled incorrectly due to a bug of the resolver pass.

The bug made swc to emit

function _setPrototypeOf(o, p) {
_setPrototypeOf =
Object.setPrototypeOf ||
function _setPrototypeOf1(o1, p1) {
o1.__proto__ = p1;
return o1;
return _setPrototypeOf1(o, p);
exports.default = _setPrototypeOf;


export default function _setPrototypeOf(o, p) {
_setPrototypeOf =
Object.setPrototypeOf ||
function _setPrototypeOf(o, p) {
o.__proto__ = p;
return o;
return _setPrototypeOf(o, p);

This is now fixed.

CR in template literals (#1549)#

Previously the code below resulted in a bug.

const { transform } = require("@swc/core");
transform("const a = `\r\n`;", {
jsc: {
parser: {
syntax: "typescript",
target: "es2015",
.then(({ code }) => code)
.then(console.log, console.error);

Input sourcemap bug (#1404)#

swc now handles input source map correctly.

Generic parsing bug (#1526)#

export const foo = function* <T>() {};
export const bar = () => {};

Prevously swc incorrectly failed emitting invalid syntax error. It was due to <T> being parsed as jsx and it's now fixed.

Dead branch remover bug (#1539)#

function test() {
return foo();
function foo() {
return 2;

is now compiled as

function test() {
function foo() {
return 2;
return foo();

Fixed by @devongovett.

TypeScript namespace bug (#1553, #1515)#

export function a() {}
export namespace a {
export function b() {}

When a typescript namespace is used with another declaration with identical name, swc produced an invalid code. It's now fixed by tracking names.

Sourcemap position bug (#1548)#

It's reported via deno.

swc emitted 0 for the column of indented nodes, which made the sourcemap unhelpful. swc now considers indention while emiiting sourcemap.

Visitor bug (#1543)#

There was a change to ast because previous design did not allow getting span of the template part of the template literal. But the node package was not updated and it's fixed by this pr.

Fixed by @arendjr.

Resolver bug relatead to function expressions (#1540)#

Previously swc compiled

export default function foo() {
foo = function foo(x) {
return x === 0 ? 1 : 1 + foo(x - 1);
return foo(10);


export default function foo() {
foo = function foo1(x) {
return x === 0 ? 1 : 1 + foo1(x - 1);
return foo1(10); // <- this is wrong

which is wrong.

The bug is fixed by @devongovett and swc now emits

test(function foo() {
foo = function foo1(x) {
return x === 0 ? 1 : 1 + foo1(x - 1);
return foo(10);

TypeScript definitions (#1542, #1535)#

Some AST type definitions are wrong, and it's now fixed by @wavesheep.

Branch simplifier bug (#1536)#

Previously the optimizer of swc broke codes like

if ( < 0) {
for (let i = 0; i < 10; i++) {
if ( < 0) {
} else {

It's now fixed by @devongovett.

TypeScript common js import bug (#1448)#

swc now supports common js import of typescript.

import F = require("yaml");

Default destructuring patterns (#1477, #1449)#

swc now supports default patterns in object patterns.

async function foo() {
const { bar: {} = {} } = baz;

this in async object methods (#1455)#

swc previously broke codes with asynchronous method like

const SampleData = typedModel(
byPlatform: async function (platform: string) {
const result = await this.find({ platform: { $eq: platform } });
return result;
SampleData.byPlatform("youtube").then((res) => {;

It's now fixed.

Type stripper bug (#1521)#

swc now allows declaring a type with name which is imported.

For example code below,

import { Test } from "test";
interface Test {}

import { Test } from "test"; is now preserved because console.log(Test); uses Test.

Fixed by @devongovett.

Comment parsing bug (#1527)#

function Bar() {
const [foo, setFoo] = useState(0);
React.useEffect(() => {
// @refresh reset
return <h1>{foo}</h1>;

swc now handles comment // @refresh reset correctly.

Abstract classes (#1454)#

export abstract class AbstractProviderDeliveryService {}

Super in class methods (#1490)#

There were some edge cases where swc emits wrong code for usages of super in class methods.

Affected code looks like

"use strict";
class Element {
getChildElements() {
return this.childElements;
class CanvasElement extends Element {
createFacets(hidden) {
const childElements = this.getChildElements();
class ColouredCanvasElement extends CanvasElement {
createFacets(hidden) {
hidden = super.createFacets(hidden); /// This line was buggy
class ColouredSquare extends ColouredCanvasElement {}
const bugExample = () => {
const colouredSquare = new ColouredSquare(),
hidden = false;
export default bugExample;

Backticks in template literals (#1488)#

Previously swc handled


in a wrong way. It's now fixed.

Declare namespace bug (#1508)#

swc preivously didn't handle declare namespace correctly. It emitted

var twttr;
(function (twttr1) {
const txt;
twttr1.txt = txt;
})(twttr || (twttr = {}));


declare namespace twttr {
export const txt: typeof import("twitter-text");

which should be an empty file. It's now fixed.

ES module interop for dynamic imports (#1480, #1509)#

Code like

const { default: ora } = await import("ora");

requires some helpers to work properly, but swc didn't use helpers.

It's now fixed and it works identically as tsc.

Parenthesis bug of class properties (#1502)#

Previously swc compiled

class A {
a = (console.log(1), 2);


class A {
a = console.log(1), 2;

but it's now

class A {
a = (console.log(1), 2);

Fixed by @nayeemrmn

Sourcemaps of multiline block comments (#1511)#

Before: Before

After: After

Fixed by @devongovett.

Generic parsing bug (#1505)#

swc has a bug related to backtracking and as a result the following code result in an exception.

type InjectedTeamsProps = {};
class Component<_T, _U> {}
class ComponentType<_T> {}
const withTeamsForUser = <P extends InjectedTeamsProps>(
_WrappedComponent: ComponentType<P>
) =>
class extends Component<
Omit<P, keyof InjectedTeamsProps> & Partial<InjectedTeamsProps>,
> {
static displayName = `x`;

This is fixed.

Class names when keepClassNames is true (#1507)#

Previously keepClassNames didn't work for class expressions. This resulted in decorated class declarations being renamed, which breaks codes depend on relfect-metadata.

Affected code looks like:

import { Entity, BaseEntity } from "typeorm";
export class Location extends BaseEntity {}

Class properties named readonly (#1514)#

swc now supports

export class ClassProp {
readonly!: boolean;

Private declare properties (#1503)#

class Class {
private declare prop;

The code above now works with swc.

Assert after imports (#1512)#

import assert from "./index";
assert<123>(123, 123);
assert<123>(123, 123, 123);

For the code above, the parser of swc tried to eat second assert to parse it as a part of an import assertion. This is fixed by checking for newlines.

New features#

TypeScript 4.3#

override (#1541)#

class SpecializedComponent extends SomeComponent {
override show() {
// ...
override hide() {
// ...

Implemented by @g-plane.


getter / setters (#1517)#

interface X {
get foo(): string;
set foo(v: string | number);
type Y = {
get bar(): string;
set bar(v: string | number);

static index signature (#1537)#

class Foo {
static hello = "hello";
static world = 1234;
static [propName: string]: string | number | undefined;

Implemented by @g-plane.


Pure annotation for react (#1564)#

swc now emits /*#__PURE__*/ for react components, which is used by various optimizers to identify side-effect-free functions.

Implemented by @devongovett.

Fast refresh (#1524)#

swc now supports react fast refresh. See docs for configurations.

Implemented by @Austaras.

UX Improvement#

Better error message for wrong configurations. (#1532)#

Previously swc sielently used default syntax for the .swcrc below.

"jsc": {
"parser": {
"syntax": "typescript",
"dynamicImport": true
"externalHelpers": true,
"target": "esnext"
"sourceMaps": true

This config is invalid because target does not allow esnext. But error message was cryptic because it was about parsing failure.

It's now fixed and swc reports proper error for such inputs.

Parser error code (#1551)#

Previously swc emiited TS1775 for the code below, but it should be TS1773.

class C implements A extends B {}

Fixed by @g-plane

Changelog: swc v1.2.51


Column position in source maps (#1470)#

Thanks to @devongovett, swc now emits correct source map regarding column offsets.

keepClassName (#1453)#

The option keepClasName was introduced in swc v1.2.50. But there was a bug at configuration merging, and it didn't work. It's now fixed.

Codegen of arrow functions (#1452)#

Arrow functions without parenthesis in arguments like async foo => 0; is now handled properly.

bundler: Stack overflow on windows (#1464)#

This was reported via deno, by #9752. Previously bunlding already-bundled file might cause stack overflow on windows, but it's now fixed.

Assignments in await argument (#1475)#

Previsouly, swc break the code like await (bar = Promise.resolve(2)); by removing parens. This is now fixed and it works properly.

Parens in nullish coalescing (#1496)#

Previously swc miscompiled

console.log(("a" ?? "b") || "");


console.log("a" ?? ("b" || ""));

which is wrong. swc now emits

console.log(("a" ?? "b") || "");

Jsx entities in jsx attribute values (#1501)#

swc now compiles

<div id="abc&gt;" />


React.createElement("div", {
id: "abc>",

regardless of target version.

Changelog: swc v1.2.50


TypeScript metadata for unions (#1421)#

Now swc emits proper metadata for union of string literals, like in codes like

import "reflect-metadata";
const COL_KEY = Symbol("col");
const column = () => {
return (object: any, key: string) => {
Reflect.defineMetadata(COL_KEY, "value", object, key);
class User {
@column() currency!: "usd" | "eur" | "yen";
console.log(Reflect.getMetadata("design:type", User.prototype, "currency"));

Previously, the code printed undefined when compiled with swc which is wrong. It is now String.

No duplicated use strict (#1423)#

For code like

"use strict";
import { arrayUtilities } from "necessary";
const { second } = arrayUtilities;
const elements = [1, 2, 3],
secondElement = second(elements);

swc now emits

"use strict";
var _necessary = require("necessary");
var second = _necessary.arrayUtilities.second;
var elements = [1, 2, 3],
secondElement = second(elements);

In previous versions, the 'use strict' directive was emitted twice.

\r\n in template literals (#1450)#

Previously swc miscompiled the code below.

import { MultipartReader } from "[email protected]/mime/multipart.ts";
import { StringReader } from "[email protected]/io/readers.ts";
// carriage returns added for running on POSIX, not needed if on windows
const content = `--------------------------366796e1c748a2fb\r
Content-Disposition: form-data; name="payload"\r
Content-Type: text/plain\r
const boundary = "------------------------366796e1c748a2fb";
const stringReader = new StringReader(content);
const multipartReader = new MultipartReader(stringReader, boundary);
const formData = await multipartReader.readForm();
for (const entry of formData.entries()) {
console.log("entry", entry);
console.log("formdata", formData);

\r\n in template literals was previously parsed as \n, but it's now parsed as \r\n.

bundler: Many improvements (#1427)#

The bundler of the swc can now handle much more codes. Various bugs are reported via deno and those are all fixed.

New option to prserve class name (#1279)#

To bypass restrictions of rust, swc uses a trick named span hygiene. It modifies identifier at the end to prevent conflict between identifiers. But this operation can be problematic if the name of class matters.

For example,

class MyClass {
prop = 1;
function Decorator(): PropertyDecorator {
return () => undefined;
class MyDecoratedClass {
@Decorator() prop = 1;

depends on the class name.

swc now has an option to preserve class name. See the documentation for .swcrc.

Fix for switch statements in loops (#1415)#

When targeting es3 or es5, swc broke some codes with switch statements in for loops like

export function test(items) {
const infoMap = new WeakMap();
for (let i = 0; i < items.length; i += 1) {
const item = items[i];
let info;
switch (item.type) {
case "branch1":
info = item.method1();
case "branch2":
info = item.method2();
case "branch3":
info = item.method3(
Object.fromEntries( => [item.alias ??, getInfo(t)])
throw new Error("boom");
infoMap.set(item, info); // important
function getInfo(item) {
if (!infoMap.has(item)) {
throw new Error("no info yet");
return infoMap.get(item);

It is now fixed.

New features#

.swcrc option to enable sourcemps. (#1309)#

Previously generating sourcemap required calling apis with proper option. But now swc has an option to enable sourcemap. See the documentation for .swcrc.

@babel/preset-modules (#1439)#

Thanks to @devongovett, swc now has an option to enable bugfix transforms, just like preset-modules of babel.

bugfix/transform-async-arrows-in-class, bugfix/transform-edge-default-parameters and bugfix/transform-tagged-template-caching is added.

Changelog: swc v1.2.48


Parsing of generics (#1405)#

The parser of swc failed to parse below code if tsx is enabled.

function foo<P extends RouteParams = RP, S extends State = RS>(
name: string,
path: string,
...middleware: RouterMiddleware<P, S>[]
): Router<P extends RP ? P : P & RP, S extends RS ? S : S & RS>;

This is reported by a deno team member via discord and now it's fixed.

await (await foo)() (#1395)#

swc now doesn't break code like below.

await(await foo)();

Catch parameters (#1413)#

swc previously miscompiled code like below.

var e = 1;
try {
throw 2;
} catch {

This was the case because the hygiene passs didn't do caclulated renaming operations while handling a catch clause. It's now fixed.

Bundler bugfixes#

Correct handling of export defaults (#1373)#

Previously the bundler miscompiled some export-default-ed functions if it depends on hoisting.

Affected code looks like

import log from "./log.js";
export default async function cli() {
log("It works!");

but it's now fixed.

Performacne improvements#

Parser performance improvement (#1411)#

This pr was intended to reduce wasted memry space and it resulted in 10% performance boost of the parser.

New features#

New jsx transforms (#1408)#

Config api is almost identical with the one of babel.

preset-env with custom config path (#1374)#

Thanks to @mcnicholls, swc now supports using .browserlistrc or package.json in any path for determining environment.

See docs for more details.


Reduction of binary size (#1418)#

Thanks to @Brooooooklyn, the binary size of swc is reduced.

Changelog: swc v1.2.47


bundler: No more infinite loop (#1369)#

This was reported by a Deno user at It was hard to debug because there was no test case, but fix was simple.

bundler: Refinsed cjs support (#1349)#

You can now use regenerator with spack, the bundler for the swc project.

Previously some cjs modules are incorrectly compiled.

bundler: Support for node js builtin modules (#1349)#

The bundler now supports importing / reexporting node js builtin modules. It currently does not touch such imports / exports.

bundler: Various bugfixes (#1349, )#

Some more bugs are fixed.

sourceMappingURL is respected (#1236)#

swc now respectes //# sourceMappingURL= in the input file.

sourceMappingURL relative to input file (#1255)#

swc now resolves source maps from two location (to prevent regression). It will try relative path first, and tries to resolve from root if source map isn't found.

Second check is to preserve breaking existing tools.

parser: Generator function with jsx enabled (#1299)#

swc can now parse code like

export const iteratorMapGenerator = function* <T, R>(
values: IterableIterator<T>,
execute: IteratorExecution<T, R>
): IterableIterator<R> {};


js api: Respect isModule: false (#1258)#

swc now supports parsing a file as script. It would be useful if you are using non-strict mode codes.

cjs: Fix for export default-ed classes (#1213)#

Previously swc miscompiled

import foo from "foo";
class OK {
constructor() {
export default class NotOK {
constructor() {


"use strict";
Object.defineProperty(exports, "__esModule", {
value: true,
exports.default = void 0;
var _foo = _interopRequireDefault(require("foo"));
function _interopRequireDefault(obj) {
return obj && obj.__esModule
? obj
: {
default: obj,
class OK {
constructor() {
class NotOK {
constructor() {
console.log(foo); // <- this is wrong
exports.default = NotOK;

which is wrong because of the line commented. It's now fixed.

typescript: Support for type-only namespaces (#1361)#

swc now correctly removes the namespace TestClass from the code below.

export class TestClass {
public testMethod(args: TestClass.TestArgs) {
return args.param1;
declare namespace TestClass {
export interface TestArgs {
param1: boolean;

New features#

bundler: Support for json modules (#1368)#

Reported as axios import error, but actually it was a bug related to importing json files.

New platform support#

windows ia32 (#1367)#

Thanks to @Brooooooklyn, swc now supports windows-ia32.

Changelog: swc v1.2.46


Enums in namespaces (#1340)#

swc had support for namespaces since v1.2.46. But the support was not complete and enums were not handled properly. v1.2.46 adds support for enums, so the code below works as expected.

namespace Test {
export enum DummyValues {
A = "A",
B = "B",

Private class properties (#1353)#

Previously, swc didn't compile some of accesses to private properties of classes. This is fixed as of v1.2.46, by visiting all children in the ast visitor.

Block scoping (#1353)#

Preivously, swc miscompiled some of loops including

function combineOverlappingMatches(matches) {
let hasOverlaps = false;
for (let i = matches.length - 1; i >= 0; i--) {
let currentMatch = matches[i];
let overlap = matches.find((match) => {
return (
match !== currentMatch && match.itemsType === currentMatch.itemsType
if (overlap) {
hasOverlaps = true;
matches.splice(i, 1);
if (hasOverlaps) {

This is now fixed by making block statement transparent in point of view of the block scoping visitor. As this fix applies to all block statements, swc would not break such loops.

This in complex async arrow (#1353)#

Previously, swc errornously changed this in the asynchronous arrow function below.

class A {
val = "1";
async foo() {
try {
return await (async (x) => x + this.val)("a"); // this is undefined
// return await Promise.all(['a', 'b'].map(async (x) => x + this.val)); // this is undefined
} catch (e) {
throw e;
new A().foo();

This is fixed as of v1.2.46. Now swc uses quite general logic for handling such code, and I expect it not to break asynchronous arrows anymore.

bundler: Reserved word as an ident (#1346)#

As the bundler of swc is falttening bundler just like rollup, it had some code to handle difference of identifier context. For example, instanceof in the code below is valid,

import * as foo from "./util";
const x = foo.instanceof;

while instanceof in the code below is invalid.

const instanceof = function () {
// ...

The bundler renames instanceof in below to something different, but it had a bug related to object patterns in assignments. This is now fixed and the bundler will not break code using reserved works in object patterns.

New feautres#

Support for legacy decorators on methods with computed keys (#1347)#

swc now supports typescript code like

class Foo {
[bar]() {}

which uses decorator with computed keys.

Support for TypeScript 4.2 (#1330)#

swc now supports parsing and transcompiling typescript 4.2 files.

Changelog: swc v1.2.45


Escapes in string literals (#1227)#

This was a regression caused by some works related to span (and sourcemaps). I fixed it and swc can emit es5 code as before.

Panic on aliased reexports (#1307)#

This is a regresssion caused by promoting namespaced re-exports like (export * as foo from 'foo') to es2020 from esnext. This is now fixed.

Private class properties (#1306)#

swc previously miscompiled

class Animal {
readonly #name: string;
constructor(name: string) {
this.#name = name;
public noise() {
return this.#name.toUpperCase();

but now swc compiles it correctly. Actaully the fix was addition of one line.

Preserve imports (#1134)#

This is also a regression, but it's now fixed.


Support for typescript namespace (#1325)#

swc now supports typescript namespace.

Changelog: swc v1.2.44


Various dce bugs (#1301)#

The dead code elimination pass of swc was too aggressive and it broke some code. It's now overly conservative, and I'll improve it over time.

Small bundler rework (#1318)#

The swc project uses very creatitve (and strange) approach to handle scoping issue because rust does not allow two mutable reference to same data. Previously, the bundler of swc tried to do something smart. I patched it to depend on the approach I mentioned and as a result, almost all bugs are fixed.

Changelog: swc v1.2.42


bundler: Handle of export * correctly. (#1264)#

Previously the bundler of [swc][] did not exclude default while handling export *. This is wrong and it's fixed. As a result, you can now export default while using export * from './foo'

export { default } from "./foo";
export * from "./foo";

The code above now works.

bundler: Fix statement ordering. (#1264)#

Order of statements are now preserved. Previously, the bundler only considers about dependancy, but it resulted in some bugs so I patched it to preserve original order.

bundler: Group statements from same module. (#1264)#

While flattening all statements, the bundler now prefers statements from same module. It will help debugging the bundle, as related statements live at simillar place.

fixer: Handle assignmnet in new exprssion correctly. (#1264)#

Previously [swc][] errornously removed parenthesis from const a = new (a = b);. It resulted in const a = new a = b;, which has different meaning.

fixer: Handle comma expression in new exprssion correctly. (#1264)#

Previously [swc][] errornously removed parenthesis from const a = new (a, b);. It resulted in const a = new a, b; , which has different meaning. This is now fixed.

bundler: Prevent duplicate variable. (#1296)#

This bug occurrs when export * as foo is mixed with export * from '' more than three times, and with import. It's now fixed and bundler bundles it correctly.

bundler: Handle keywords. (#1296)#

EcmaScript allows using keywords as an identifier in some places. As the bundler flatten statements, it made a variable named instanceof when it met export { foo as instanceof }.

But this is a bug and it's now renamed to something other.

dce: Prevent tags in tagged template literals. (#1296)#

The dce was too aggresive and it removed tagged template literals. It now preserves as tagged template literals can have side effect.


If you are using some old target, you are not affected.

dce: Handle throw statement correctly. (#1296)#

Again, it errornously removed something used by throw statement. I patched it to mark argument as used correctly.