-
Notifications
You must be signed in to change notification settings - Fork 105
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
Leave natural this
in the decorator functions
#487
Comments
That 2ality arrow-function example will always work regardless what the spec chooses to do, because the arrow function always captures (or "closes over") Are you suggesting that That would be interesting! Whereas This would simply work: class Foo {
decorate() {
console.log(this instanceof Foo) // true
}
}
const foo = new Foo()
@foo.decorate
class A {}
// Outputted "true" to console. That's nice! It is not too late to change this part of the design because no JS runtime has implemented decorators yet. |
Note that |
Allow me to summarize what I have understood up to this point. Current specification class Decorator {
name = "Decorator factory";
check(value, context) {
console.log('decorator call');
console.log('this', this);
console.log('value', value);
console.log('context', context);
}
}
const decorator = new Decorator;
@decorator.check
class C {
@decorator.check
m() {}
}
Workarround: arrow function class Decorator {
name = "Decorator factory";
check = (value, context) => {
console.log('decorator call');
console.log('this', this);
console.log('value', value);
console.log('context', context);
}
}
const decorator = new Decorator;
@decorator.check
class C {
@decorator.check
m() {}
}
Workarround: the method return the decorator class Decorator {
name = "Decorator factory";
check() {
const _this = this;
return function(value, context) {
console.log('decorator call');
console.log('this', this);
console.log('_this', _this);
console.log('value', value);
console.log('context', context);
}
}
}
const decorator = new Decorator;
@(decorator.check)()
class C {
@(decorator.check)()
m() {}
} 4.- With a method that returns the decorator we can keep the original by closure, but the method call must be as a expression. Question @pzuraq, why is it not possible to keep the natural |
I think this may have been a mistake in the spec, I can't think of a reason that we would have wanted to change |
Is this change still planned? I've been playing around with decorators in TS 5.0's support and I was wanting to have some decorators as methods of a class. (As far as I can tell in the current spec it just calls the decorator unconditionally with |
This is still planned, yes. However as a normative change now it will need to go through committee first. |
For more details, see this issue: tc39/proposal-decorators#487
This has been resolved, natural |
Updates - Refactor to use ClassElementDefinition more extensively - Separate parsing class elements and defining them so that we can control the order of definition and decorator application - Extract and centralize class element decoration into a single place - Fix completions in ClassDefinitionEvaluation (need to reset the env after each possible abrupt completion). - Refactor adding private methods to instance to pull directly from `Class.[[Elements]]`, so we don't have multiple sources of truth for the elements that are defined on a class. `Class.[[Elements]]` is the canonical source of truth after ClassDefinitionEvaluation, and any operations afterward such as instantiation should base themselves on that. - Refactor to use anonymous function syntax. Non-normative fixes Fixes based on feedback from @jmdyck Remove dynamic [[HomeObject]] from decorator return values Throw an error if the value passed to `addInitializer` is not callable Set the name of the `addInitializer` function Remove setFunctionName from decorator application Call decorators with their natural `this` value. For more details, see this issue: tc39/proposal-decorators#487 Reverse initializer order Update field and accessor extra initializers to run after definition
Currently
In the specification, the decorator functions have a call that sets the value
undefined
tothis
.Curiously, in the current implementation of Babel
this
istrue
in all cases except for class decorators, in whichthis
is the decorator function (the natural behavior):The output for the method decorator is:
The output for the class decorator is:
Why is
this
undefined
?In some discussions, it was suggested that
this
could be the decorated element, but this option brought a lot of problems and side effects. Probably, the solution was made to assign the valueundefined
tothis
to avoid these problems.In my humble opinion, forcing the
undefined
value inthis
is an over-specification, and it would be correct to let the decorator function have the naturalthis
that it has.Advantages of leaving
this
of the decorating function in a natural wayA class could be considered a decorator factory, where when we create an instance, we generate a reference that can use for all calls to a method as a decorator.
An example of this behavior can be seen here: JavaScript metaprogramming with the 2022-03 decorators API (2ality.com)
As I understand it, if Babel followed the specification, this example would not be possible. Please correct me if I am wrong.
Proposal of update
Remove the assignment of
this
with theundefined
value in the decorator function call. It's a minor change but essential.The text was updated successfully, but these errors were encountered: