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

es2022 decorated class with static field initialization runtime error #48818

Closed
muhammad-salem opened this issue Apr 23, 2022 · 9 comments
Closed
Labels
Duplicate An existing issue was already created

Comments

@muhammad-salem
Copy link

Bug Report

πŸ”Ž Search Terms

decorated class with static field initialization runtime error

πŸ•— Version & Regression Information

Typescript version 4.6.2
Target: ES2022
Module: ES2022

  • This changed between versions 4.5.5 and 4.6.2

⏯ Playground Link

Playground link with relevant code

πŸ’» Code

function decorator(name: string): any {
  return () => console.log(name)
}

@decorator("break")
class BreakStatement {
    static BreakSymbol = Symbol.for('break');
    static BREAK_INSTANCE = Object.freeze(new BreakStatement(BreakStatement.BreakSymbol));
    constructor(public symbol: Symbol){}
};

πŸ™ Actual behavior

  • compile successfully and print 'break' at runtime
  • at run time

Screenshot from 2022-04-23 12-56-13

πŸ™‚ Expected behavior

no runtime error and print 'break'

execute static BREAK_INSTANCE = Object.freeze(new BreakStatement(BreakStatement.BreakSymbol));
after the decorator applied

OR
execute decorator definition in the first static initialization block

"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var BreakStatement_1;
function decorator(name) {
    return () => console.log(name);
}
let BreakStatement = BreakStatement_1 = class BreakStatement {
    static {
        BreakStatement_1 = __decorate([
            decorator("break"),
            __metadata("design:paramtypes", [Object])
        ], BreakStatement);
    }
    symbol;
    static BreakSymbol = Symbol.for('break');
    static BREAK_INSTANCE = Object.freeze(new BreakStatement_1(BreakStatement_1.BreakSymbol));
    constructor(symbol) {
        this.symbol = symbol;
    }
};

Screenshot from 2022-04-23 12-57-31

@MartinJohns
Copy link
Contributor

MartinJohns commented Apr 23, 2022

Sounds like a duplicate of #44908.

But good news: Since the decorators proposal recently hit stage 3, we might get actual support for decorators in TypeScript in one of the next versions.

@muhammad-salem
Copy link
Author

sorry for the duplication

Sounds like a duplicate of #44908.

sorry for the duplication

But good news: Since the decorators proposal recently hit stage 3, we might get actual support for decorators in TypeScript in one of the next versions.

yes it is a good news

@andrewbranch andrewbranch added the Duplicate An existing issue was already created label Apr 25, 2022
@andrewbranch
Copy link
Member

You probably want to set useDefineForClassFields: false or use a lower target. Related: #48814

@muhammad-salem
Copy link
Author

no, this doesn't solve the problem

useDefineForClassFields: false

it didn't solve the problem

Screenshot from 2022-04-26 11-30-57

the 'static initialization blocks' is running before define BreakStatement_1

@muhammad-salem
Copy link
Author

  • you can't apply the decorators after executing the static initialization blocks, that will mean you have an old code still runnig before appliying the decorators

let assume that an decorator 'logger' is applied on method

function logger(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
  const original = descriptor.value;

  descriptor.value = function (...args: any) {
    console.log('params: ', ...args);
    const result = original.call(this, ...args);
    console.log('result: ', result);
    return result;
  }
}

class Foo {
  static instance = new Foo('instance');
  static {
    // logger is not applied yet
    console.log('instance 4 + 6 = ', Foo.instance.add(4,6));
  }
  constructor(private name: string){}
  @logger
  add(x: number, y:number ) {
    console.log('name', this.name);
    return x + y;
  }
}

const foo = new Foo('foo');

console.log('instance 4 + 1 = ', Foo.instance.add(4,1)); // run normal as expected, after apply the MethodDecorator
console.log('foo 1 + 2 = ', Foo.instance.add(1,2)); // run normal as expected, after apply the MethodDecorator

@logger Playground Link

Screenshot from 2022-04-26 11-50-00

@fatcerberus
Copy link

fatcerberus commented Apr 26, 2022

Your playgrounds all have target set to ES3, which is weird since you claim to be using ES2022 in the OP. Any target other than ES3 seems to work (and there's really no reason to target that low unless you intend to run on, say, IE 6 or something).

@MartinJohns
Copy link
Contributor

MartinJohns commented Apr 26, 2022

@fatcerberus That's a bug of the playground (applies to target=9 as well): microsoft/TypeScript-Website#1136

It's a visual issue. You can see in the sidebar that the target is not really ES3, because there are no classes in ES3.

edit: Not sure why this confuses Andrew. :-D

@typescript-bot
Copy link
Collaborator

This issue has been marked as a 'Duplicate' and has seen no recent activity. It has been automatically closed for house-keeping purposes.

@andrewbranch
Copy link
Member

Not sure why this confuses Andrew

It’s more of a sad face at the playground bug

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Duplicate An existing issue was already created
Projects
None yet
Development

No branches or pull requests

5 participants