tc39/proposal-decorators

Order of execution

Closed this issue · 3 comments

I'm not quite understand how the order of execution of decorators is defined. So, instead of reading the specification (which out of my understanding), I just write some code on the babel and the javascriptdecorators.org mentioned in readme. And unluckily, they do not agree with each other. So I want to add an issues to ask for clarify the order of execution for the decorators.

My code is given below

class X {
  @X.decorator
  static w2() { return 'w2'; }
  @X.decorator
  static y2() { return 'y2'; }
  @X.decorator
  static decorator(value) {
    console.log(' value.name=' + value.name);
    return function wrapped(value) {
      console.log('>value.name=' + value.name);
    };
  }
  @X.decorator
  static w1() { return 'w1'; }
  @X.decorator
  static y1() { return 'y1'; }
}

@X.decorator
class Y {}

Babel:

>value.name=w2
>value.name=y2
>value.name=decorator
>value.name=w1
>value.name=y1
 value.name=Y

javascriptdecorators.org:

 value.name=y1
 value.name=w1
 value.name=decorator
>value.name=y2
>value.name=w2
>value.name=Y

Also, if I remove the w2 and y2, javascriptdecorators.org only get cossponding output removed, but Babel reports:

 value.name=decorator
 value.name=w1
 value.name=y1
>value.name=Y

Apologice, the javascriptdecorators.org transpiler is wrong. The normative implementation is followed by Babel, Typescript and, in the near future, browser javascript engines.

Apologice, the javascriptdecorators.org transpiler is wrong. The normative implementation is followed by Babel, Typescript and, in the near future, browser javascript engines.

But I believe the behavior in Babel is also far from correct (or rational) currently.

I transpiled your code sample using babel's repl but running it threw an error:

ReferenceError: can't access lexical declaration 'X' before initialization

So changed it to the following:

function decorator(value) {
  console.log(' value.name=' + value.name);
  return function wrapped(value) {
    console.log('>value.name=' + value.name);
  };
}

class X {
  @decorator
  static w2() { return 'w2'; }
  @decorator
  static y2() { return 'y2'; }
  @decorator
  static decorator(value) {
    console.log(' value.name=' + value.name);
    return function wrapped(value) {
      console.log('>value.name=' + value.name);
    };
  }
  @decorator
  static w1() { return 'w1'; }
  @decorator
  static y1() { return 'y1'; }
}

@decorator
class Y {}

transpiled it and ran it to get the following:

 value.name=w2
 value.name=y2
 value.name=decorator
 value.name=w1
 value.name=y1
 value.name=Y

Which I believe makes sense...