Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

undefined is passed for the "context.metadata" field in a decorator metadata #7957

Closed
arklanq opened this issue Sep 15, 2023 · 12 comments · Fixed by #8097
Closed

undefined is passed for the "context.metadata" field in a decorator metadata #7957

arklanq opened this issue Sep 15, 2023 · 12 comments · Fixed by #8097
Labels
Milestone

Comments

@arklanq
Copy link

arklanq commented Sep 15, 2023

Describe the bug

When switching from tsc to swc to transpile TypeScript to JavaScript code I have noticed that context.metadata argument for decorators becomes undefined.

More context:

  • I am trying to replace tsc with swc for faster source code transpilation in a relatively modern Node.js app.
  • I am using '2022-03' decorators ("stage 3 decorators"), see swc config below.
  • I am using the latest version of TypeScript (5.2+).
  • I am using SWC within Rollup bundler, thanks to rollup-plugin-swc3 package.
  • I have polyfilled decorator-metadata feature for my node.js with core-js/proposals/decorator-metadata-v2.js.

Input code

type ClassTarget = abstract new (...args: unknown[]) => unknown;

function inject<Class extends ClassTarget>(
  target: Class,
  context: ClassDecoratorContext<Class>
): void {
  console.debug(context.metadata); // undefined
}

@inject
class App {

  foo() {
    return 'bar';
  }

}

const app = new App()
app.foo();

Config

const config = {
    // --- Plugin options
    include: /\.ts$/,
    exclude: /node_modules/,
    tsconfig: 'tsconfig.json',
    // --- SWC options
    env: {
      targets: 'node >= 18.14',
      // 'entry' mode imports too much polyfills
      // 'usage' mode doesn't work as expected
      mode: undefined,
      coreJs: coreJsPackageManifest.version,
      dynamicImport: true,
    },
    jsc: {
      parser: {
        syntax: 'typescript',
        tsx: false,
        decorators: true,
        dynamicImport: true,
      },
      transform: {
        // Stage 3 decorators
        decoratorVersion: '2022-03',
      },
      externalHelpers: true,
      keepClassNames: true,
      // Use `env` option instead
      target: null,
    },
    minify: PRODUCTION_BUILD,
    sourceMaps: true,
  }

Playground link

https://play.swc.rs/?version=1.3.74&code=H4sIAAAAAAAAA02QwU7EIBCG7zzF3BYSw95b22jWR%2FBm9jCF6aa6Dg1MdzXGd3eENTHhwPzwffxBPleCwxlLecZ8IoEBcCqSMQgwXcF67%2FWgdLDxG6crvxwdDOPf1BszbxxkSQwLv1KQ%2ByoD%2BhDiWP6rR2sApG67lt9pEBKLXr4lTxRSRkn50OJmG43r4JKWCF%2BNKOlMPtK0neyN9%2B8kGFHQ9bDfa71I88IUzbcxD62ZCbXZ47qqRj1zStZVI0Am2TLDbsK86zVRStfvSwKowFA%2FQ1HrjM6%2Bsr35AYrFObg%2BAQAA&config=H4sIAAAAAAAAA22QPQ%2BCQAyGd3%2FFpbMaQQdjoouLLo7uDRSDwt2lrQZC%2BO8efiAap7bv0%2B9mZAycJYGVaYIbAo8sxH0cFKmtYhUU0NqTJJx7hfGbqnQow0Ko11JKHKM6loCUrwNSWyzzZF96x%2FoF26cBZbSSOS6HK%2FQNj8SSO9stE8%2FieDKbw3c5VUpssdhR4elnPlyI%2FLZAkQOWNGSPaiB7%2B%2FxBkU%2BkXRJYl5LZrE20nEaL17y%2Fl3SdRu0dcYStD1QBAAA%3D

SWC Info output

Operating System:
    Platform: darwin
    Arch: arm64
    Machine Type: arm64
    Version: Darwin Kernel Version 22.6.0: Wed Jul  5 22:22:52 PDT 2023; root:xnu-8796.141.3~6/RELEASE_ARM64_T8103
    CPU: (8 cores)
        Models: Apple M1

Binaries:
    Node: 18.17.0
    npm: 9.8.1
    Yarn: 1.22.19
    pnpm: N/A

Relevant Packages:
    @swc/core: 1.3.82
    @swc/helpers: 0.5.1
    @swc/types: 0.1.4
    typescript: 5.2.2

SWC Config:
    output: N/A
    .swcrc path: N/A

Next.js info:
    output: N/A

Expected behavior

With tsc:

function someDecorator(...) {
  console.log(context.metadata) // [Object: null prototype] {}
}

Actual behavior

With swc:

function someDecorator(...) {
  console.log(context.metadata) // undefined
}

Version

1.3.82

Additional context

Maybe this could be helpful:
microsoft/TypeScript#55453

@arklanq arklanq added the C-bug label Sep 15, 2023
@kdy1 kdy1 added this to the Planned milestone Sep 16, 2023
@arklanq
Copy link
Author

arklanq commented Sep 16, 2023

I have investigated the issue a bit more and found out that the decorators' metadata doesn't work at all.
Metadata is not saved after modifications are made in decorator body, have a look at an example below:

type ClassTarget = abstract new (...args: unknown[]) => unknown;

function inject<Class extends ClassTarget>(
  target: Class,
  context: ClassDecoratorContext<Class>
): void {
  context.metadata = Object.create(null); // Manually initializing metadata object, the same way tsc does
  context.metadata.foo = 'bar'; // Seeding example data
}

@inject
class App { }
// tsc
console.debug(App[Symbol.metadata]); // [Object: null prototype] { "foo": "bar" }
// swc
console.debug(App[Symbol.metadata]); // null

@kdy1 kdy1 closed this as completed Sep 16, 2023
@arklanq
Copy link
Author

arklanq commented Sep 16, 2023

I think swc is emitting the expected output for your repro.

https://play.swc.rs/?version=1.3.85&code=H4sIAAAAAAAAA02QwU7EIBCG7zzF3BYSw95b22jWR%2FBm9jCF6aa6Dg1MdzXGd3eENTHhwPzwffxBPleCwxlLecZ8IoEBcCqSMQgwXcF67%2FWgdLDxG6crvxwdDOPf1BszbxxkSQwLv1KQ%2ByoD%2BhDiWP6rR2sApG67lt9pEBKLXr4lTxRSRkn50OJmG43r4JKWCF%2BNKOlMPtK0neyN9%2B8kGFHQ9bDfa71I88IUzbcxD62ZCbXZ47qqRj1zStZVI0Am2TLDbsK86zVRStfvSwKowFA%2FQ1HrjM6%2Bsr35AYrFObg%2BAQAA&config=H4sIAAAAAAAAA22QsQ6CQAyGd5%2Fi0lmNoIMx0cVFF0f3BopB4e7SVgMhvLsHKmLidO3%2FXdu%2FbSbGwFUS2JgmhCHxyEI85EGR2ipWQQGtPUnCuVeYfqhKhzIshAYtpcQxqmMJSPk%2BIrXFMk%2BOpXesP7B9PaCMVjLH5djC0PBMLLmznZl4EcezxRJ%2By6lSYovFgQpP%2FfyRNbgR%2BX2BIicsaWyuLweyj%2B8hFPlC2n0C61Iyu62J1vNo9R74d5Wu06R9AlfYLbtVAQAA

Mmm... it does not for me. I have copy-pasted the code from output to a plain javascript file and when executed with Node.js got the same results. Still context.metadata remains undefined.

PS: I have also upgraded all related dependencies so all the tests I run are based on the latest versions of @swc/*.

-  "@swc/cli": "^0.1.62",
-  "@swc/core": "^1.3.82",
-  "@swc/helpers": "^0.5.1",
+  "@swc/cli": "^0.1.62",
+  "@swc/core": "^1.3.85",
+  "@swc/helpers": "^0.5.2",

@kdy1
Copy link
Member

kdy1 commented Sep 16, 2023

If so, please provide a minimal reproduction, ideally with the swc playground.

@kdy1
Copy link
Member

kdy1 commented Sep 16, 2023

Your code does not produce undefined.

image

What browser do you use?

@arklanq
Copy link
Author

arklanq commented Sep 17, 2023

@kdy1 Ahh, you don't see the output, as I am using console.debug which is unsupported in a browser environment.

Let me start from scratch with (this time) valid and a bit more descriptive reproduction:

Issue reproduction / Github

https://github.com/arklanq/swc-issue-7957-reproduction

Issue reproduction / CodeSandbox

https://codesandbox.io/p/sandbox/crazy-mopsa-n9tgzv?welcome=true

Issue reproduction / SWC Playground

I cannot create valid issue reproduction on SWC Playground, because I need to import

Please make sure to read README.md and the comments left in the code carefully.

@kdy1
Copy link
Member

kdy1 commented Sep 18, 2023

I looked at the spec and seems like the babel team just didn't implement it yet.

https://github.com/tc39/proposal-decorators

I think that's because it is not worth the cost, but well... I'll reopen this issue for now.

@kdy1 kdy1 reopened this Sep 18, 2023
@kdy1 kdy1 changed the title "undefined" passed for the "context.metadata" field in a decorator metadata undefined is passed for the "context.metadata" field in a decorator metadata Sep 18, 2023
@arklanq
Copy link
Author

arklanq commented Sep 18, 2023

@kdy1 This is a fairly new feature that was introduced recently in TypeScript 5.2, so maybe Babel team is not rushing to implement it now. Anyway, it is a stage 3 proposal so we can be almost sure the feature will land soon in ECMA standard so we should not ignore it.

Some reference:

@kdy1
Copy link
Member

kdy1 commented Sep 18, 2023

There are enormous amount of tasks that has higher priority than 100% parity with the specification.

@arklanq
Copy link
Author

arklanq commented Sep 18, 2023

Sure, I'll keep an eye on the issue then.

kdy1 pushed a commit that referenced this issue Oct 16, 2023
**Description:**

This PR implements the [decorator
metadata](https://github.com/tc39/proposal-decorator-metadata) proposal,
that is now at Stage 3.

As the decorator metadata proposal is a small extension of the decorator
proposal and is not possible to compile the metadata without transpiling
decorators, I opted to implement it into the existing decorator
transformer (and helper)

**Related issue:**

 - Closes #7957
@kdy1 kdy1 modified the milestones: Planned, v1.3.94 Oct 21, 2023
@swc-bot
Copy link
Collaborator

swc-bot commented Nov 20, 2023

This closed issue has been automatically locked because it had no new activity for a month. If you are running into a similar issue, please create a new issue with the steps to reproduce. Thank you.

@swc-project swc-project locked as resolved and limited conversation to collaborators Nov 20, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Development

Successfully merging a pull request may close this issue.

3 participants