oven-sh / bun

Incredibly fast JavaScript runtime, bundler, test runner, and package manager – all in one
https://bun.sh
Other
74.17k stars 2.77k forks source link

Problem with decorators: Reflect.hasOwnMetadata is not a function. #11152

Closed PodaruDragos closed 1 week ago

PodaruDragos commented 5 months ago

What version of Bun is running?

1.1.7+b0b7db5c0

What platform is your computer?

Microsoft Windows NT 10.0.22631.0 x64

What steps can reproduce the bug?

While using inversify.js i get the error in the title.

Steps to reproduce this:

Create 3 files like so.

File 1

// index.ts
import 'reflect-metadata';
import { what } from './file-3.js';

File 2

file-2.ts
import { inject, injectable } from 'inversify';

@injectable()
export class Child {
  public test() {
    return 'test';
  }
}

@injectable()
export class Test {
  constructor(
    @inject('CHILD') private child: Child
  ) { }

  public test() {
    return this.child.test();
  }
}

File 3

import { Container } from 'inversify';
import { Child, Test } from './file-2.js';

class CContainer {
  public container: Container;
  constructor() {
    this.container = new Container();
    this.container.bind('CHILD').to(Child);
    this.container.bind('TEST').to(Test);
  }
}

const cc = new CContainer();
const test = cc.container.get<Test>('TEST');

export const what = (): string => {
  return test.test();
};

Run bun run index.ts and you should get the error.

What is the expected behavior?

I would expect the output to be test

What do you see instead?

TypeError: Reflect.hasOwnMetadata is not a function. (In 'Reflect.hasOwnMetadata(metadataKey, annotationTarget)', 'Reflect.hasOwnMetadata' is undefined)

Additional information

If all the code is one file, it works just fine

ghost commented 5 months ago

This has to do with the fact that bun does not use the same global for all modules (or so it seems)

craigcWC3 commented 3 weeks ago

Is there a way to up-vote this? We are running into the same problem and it is currently our roadblock to moving to bun.

PodaruDragos commented 3 weeks ago

Code snippet simplified for what's blocking us

  import "reflect-metadata";

  import { controller, InversifyExpressServer } from "inversify-express-utils";
  import { Container, inject, injectable } from "inversify";

  @injectable()
  export class Child {
    public test() {
      return "test";
    }
  }

  @injectable()
  export class Test {
    constructor(@inject("CHILD") private child: Child) {}

    public test() {
      return this.child.test();
    }
  }

  @controller("/test")
  export class TestController {
    constructor(@inject("TEST") private testService: Test) {}

    public async test(): Promise<string> {
      return Promise.resolve(this.testService.test());
    }
  }

  class IocContainer {
    public container: Container;
    constructor() {
      this.container = new Container();
      this.container.bind("CHILD").to(Child);
      this.container.bind("TEST").to(Test);
    }
  }

  const iocContainer = new IocContainer();

  let server = new InversifyExpressServer(iocContainer.container);
  server.setConfig((app) => {});

  let app = server.build();
  app.listen(3000);

and this errors with

  return metadatas;
  59 | }
  60 | function _tagParameterOrProperty(metadataKey, annotationTarget, key, metadata) {
  61 |     var metadatas = _ensureNoMetadataKeyDuplicates(metadata);
  62 |     var paramsOrPropertiesMetadata = {};
  63 |     if (Reflect.hasOwnMetadata(metadataKey, annotationTarget)) {

TypeError: Reflect.hasOwnMetadata is not a function. (In 'Reflect.hasOwnMetadata(metadataKey, annotationTarget)', 'Reflect.hasOwnMetadata' is undefined)

Same code works just fine with ts-node

PodaruDragos commented 1 week ago

with the latest version of bun and inversify-express-utils this code now works correctly. I am closing this