Skip to content

Referencing Decorated Class in Parameter-Decorator #1278

@Nerixyz

Description

@Nerixyz

Describe the bug

If the decorated class is referenced in a parameter-decorator, swc produced an "invalid" output. The output tries to access the class before it's initialized causing the following error message: ReferenceError: Cannot access 'MyClass' before initialization

Input code

type Klass<T = any> = {new (...args: any[]): T};
function MyDecorator(klass: Klass): PropertyDecorator {
    return () => {
        // do something
        console.log(klass);
    }
}

class MyClass {
    @MyDecorator(MyClass) prop: '';
}

console.log(new MyClass());

Config

{
     "jsc": {
        "parser": {
            "syntax": "typescript",
            "tsx": false,
            "decorators": true,
            "dynamicImport": false
        },
        "externalHelpers": false,
        "target": "es2020",
        "loose": true,
        "transform": {
            "legacyDecorator": false,
            "decoratorMetadata": true
        }
    },
    "module": {
        "type": "commonjs",
        "strictMode": true
    }
}

Expected behavior

Compiling the same code with tsc --experimentalDecorators true -t ES2020 yields the following result:

var __decorate  // ...

function MyDecorator(klass) {
    return ()=>{
        // do something
        console.log(klass);
    };
}
class MyClass {
}
__decorate([
    MyDecorator(MyClass)
], MyClass.prototype, "prop", void 0);
console.log(new MyClass());

SWC Output
This is (part of) the code, swc outputs:

function _applyDecoratedDescriptor(target, property, decorators, descriptor, context) {/* ... */}
function _initializerDefineProperty(target, property, descriptor, context) {/* ... */}

var _class, _descriptor;
function MyDecorator(klass) {
    return ()=>{
        // do something
        console.log(klass);
    };
}
// here, the class is accessed
var _dec = MyDecorator(MyClass), _dec1 = typeof Reflect !== "undefined" && typeof Reflect.metadata === "function" && Reflect.metadata("design:type", String);
let MyClass = ((_class = function() {
    class MyClass1 {
        constructor(){
            _initializerDefineProperty(this, "prop", _descriptor, this);
        }
    }
    return MyClass1;
}()) || _class, _descriptor = _applyDecoratedDescriptor(_class.prototype, "prop", [
    _dec,
    _dec1
], {
    configurable: true,
    enumerable: true,
    writable: true,
    initializer: void 0
}), _class);
console.log(new MyClass());

Version
The version of @swc/core: 1.2.40

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions