swc icon indicating copy to clipboard operation
swc copied to clipboard

Decorator's context access has the wrong behaviour

Open Jamesernator opened this issue 2 years ago • 0 comments

Describe the bug

The behaviour of decorator's context.access object is wrong, it acts expecting a this value but actually the behaviour should take in values as functions.

Input code

function captureCtx(fn: (ctx: ClassFieldDecoratorContext) => void) {
    return function decorate<T>(value: T, ctx: ClassFieldDecoratorContext): T {
        fn(ctx);
        return value;
    };
}

let ctx!: ClassFieldDecoratorContext;

class Foo {
    @captureCtx(($ctx) => {
        ctx = $ctx;
    })
    x = 3;
}

const foo = new Foo();
console.log(ctx.access.get(foo));

Config

{
  "jsc": {
    "parser": {
      "decorators": true,
      "syntax": "typescript",
      "tsx": false
    },
    "transform": {
      "decoratorVersion": "2022-03"
    },
    "target": "es2022"
  },
  "isModule": true
}

Playground link (or link to the minimal reproduction)

https://play.swc.rs/?version=1.3.106&code=H4sIAAAAAAAAA4WPzwrCMAzG732KCB5akF28bU6EiU%2FgC5QulUFpZM10IL67zZx%2FTppL4MuX35f4ITruKIKzZx56bHjUPpagHY8lNMGmdOgwtHt01FumvqHIOLKBegsX6loDNwW5eszrEfyL1z4XcHPc6osNA5ZwXME%2FajbNPCkf5QxTvYU5ZOI91Xul7koFZEEvfrErpZwM4UA0Z%2By%2BntZLiZKvPvlZgRpkMIeZqYm4nnIdxcTgM7CGiFdB63yuyBSwCHSSBwrrHKZUnJB19prseADA9UEBdwEAAA%3D%3D&config=H4sIAAAAAAAAA22OzwrCMAyH732KkrPCqDffwav30GVSmW1JMnCMvbvN1IHgLb%2Fvy7%2FFeQ93iXD2SytbqMhCvOdGeoqFUQtLo8oTHb5G5qz4bBR0riSRU1XYrYqpAUehDa1vA8qYZSj8%2BHvkSiypZFsauhCO3Ql%2Bp5FvpKZJrMHs5iDJpfTTSJ8v3epewb1htd4AAAA%3D

SWC Info output

This is happening as part of Deno not using swc standalone.

Expected behavior

A 3 should be printed.

Actual behavior

undefined is printed instead.

Version

1.3.106

Additional context

The behaviour in swc is from an older version of the decorators spec, the spec has since changed to make the type of context.access:

type ClassFieldDecoratorContext<This, T> ={
    // ...
    access: {
        get: (value: This) => T,
        has: (value: This) => boolean,
        set: (value: This, value: T) => void,
    },
}

This needs to be changed for accessor members as well.

The TypeScript transform has the correct behaviour.

Jamesernator avatar Jan 25 '24 10:01 Jamesernator