swc: Circular class imports break when upgrading 1.2.205 -> 1.2.206
Describe the bug
When upgrading from 1.2.205 to 1.2.206, SWC changes how it compiles exports.
In version 1.2.205:

In version 1.2.206:

I have a bunch of model classes in my codebase, which of course circularly reference each other.
To avoid circularity problems, the ORM I use uses the “late binding” hack popular in the JavaScript community, referencing bindings with anonymous functions, e.g. @OneToMany(() => Book)
instead of just @OneToMany(Book)
. However, this seems to no longer work after the compilation change of SWC 1.2.206.
Input code
// Person.ts
import { Book } from "./Book";
export class Person {
books = new Collection<Book>();
}
// Book.ts
import { Person } from "./Person";
export class Book {
author?: Person;
}
Config
{
"jsc": {
"parser": {
"syntax": "typescript",
"tsx": false,
"decorators": true,
"dynamicImport": true
},
"transform": {
"legacyDecorator": true,
"decoratorMetadata": true
},
"target": "es2018",
"baseUrl": "src",
"paths": {
"lib/*": ["lib/*"],
"app/*": ["app/*"],
"fixtures/*": ["fixtures/*"],
"test-utils/*": ["test-utils/*"]
}
},
"module": {
"type": "commonjs"
}
}
Playground link
No response
Expected behavior
Running this code after building it, or running it with node -r @swc/register
should work.
Actual behavior
Running the code after building it, or running it with node -r @swc/register
, produces this error:
$ NODE_ENV=script node -r @swc/register src/fixtures/command.ts reapply
/Users/kelley/mywheels/api/src/app/core/models/Fleet.ts:6
get: ()=>Fleet,
^
ReferenceError: Cannot access 'Fleet' before initialization
at Object.get [as Fleet] (/Users/kelley/mywheels/api/src/app/core/models/Fleet.ts:16:14)
at Object.<anonymous> (/Users/kelley/mywheels/api/src/app/core/models/FleetContractType.ts:13:16)
at Module._compile (node:internal/modules/cjs/loader:1103:14)
at Module._compile (/Users/kelley/mywheels/api/node_modules/pirates/lib/index.js:99:24)
at Module._extensions..js (node:internal/modules/cjs/loader:1157:10)
at Object.newLoader [as .ts] (/Users/kelley/mywheels/api/node_modules/pirates/lib/index.js:104:7)
at Module.load (node:internal/modules/cjs/loader:981:32)
at Function.Module._load (node:internal/modules/cjs/loader:822:12)
at Module.require (node:internal/modules/cjs/loader:1005:19)
at require (node:internal/modules/cjs/helpers:102:18)
error Command failed with exit code 1.
Version
1.2.206
Additional context
No response
About this issue
- Original URL
- State: closed
- Created 2 years ago
- Reactions: 16
- Comments: 35 (16 by maintainers)
For those using TypeORM, using the
Relation
type resolved the issue for me https://typeorm.io/#relations-in-esm-projects@magic-akari
It turns out that indeed, the
Relation<>
trick, as described in https://github.com/swc-project/swc/issues/5047#issuecomment-1188874962, indeed also works for MikroORM.(And in fact, in most situations our codebase already uses MikroORM’s
IdentifiedReference<>
, which effectively also solves it, I just apparently hadn’t applied it everywhere yet in our codebase, and hence kept running into the bug.)Thanks for helping!
Oh, that’s a terrible reason. If someone really doesn’t want hoisted import, there’s a TS syntax
import x = require()
for them.Yes, @Nesci28 is correct that that
defineProperty
change per1.2.206
causes the bug (whether indirectly or not).I made a small repo with a reproduction of the bug, as it occurs in our codebase, that uses MikroORM (and reflect-metadata):
Indeed, I’m not sure “whose bug” this is. Whether it’s swc, MikroORM, or reflect-metadata. But the combination breaks.
I’d love to resolve the situation though, because I’m currently stuck on swc
1.2.205
😃Same issue in a NestJS project with Circular dependancies in the DI. swc/core version to 1.2.205 does not have that bug.
Manually droping the lines:
Below the line:
Fixes the issue.
check https://github.com/swc-project/swc/issues/5047#issuecomment-1188874962