javascript-decorators icon indicating copy to clipboard operation
javascript-decorators copied to clipboard

Unspecified behaviour for distant setters and getters

Open yuchi opened this issue 9 years ago • 4 comments

Sorry if it’s just me missing something.

When specifying get/set property accessors both on classes and object notation we’re allowed to separate the two, therefore, following this specification, this has unspecified behaviour:

class C {
 @F
 get prop() { }

 interstitial() { }

 @G
 set prop(v) { }
}

const obj = {
 @F
 get prop() { }

 interstitial() { }

 @G
 set prop() { }
}

What should this desugar to?

Also, inside F or G you have no information about where it was called. Was it the getter or the setter accessor?

yuchi avatar Mar 11 '15 09:03 yuchi

@yuchi the idea is that those decorators are invoked on the getter/setter pair, since internally, they are represented as a single thing.

I can see why that might not be optimal for all cases, but I'm wary of adding additional flags or metadata that could not be represented using the descriptor API.

Thoughts?

wycats avatar Mar 14 '15 23:03 wycats

The issue is that get/set shorthands represent at the same time a property and function (each).

So every function decorator must include something in the form of:

function MyDecorator(descriptor) {
  if ('value' in descriptor) return somethingWithValue(descriptor);
  else return somethingWithAccessors(descriptor);
}

Probably a good idea would be to have a meta flag (I don’t like that too) that informs that the decorator is applied to a class-method/obj-function-shorthand or a property accessor. A different API could do the job in a more explicit way. But now the idea of decorators as simple functions is great, losing it in favor of type Decorator: { property:Fn, accessor:Fn, method:Fn } is not appealing.

Yet we’re not solving the issue at hand.

I’m thinking about a @RunOnce decorator. It’s clearly function oriented. When I apply that to set prop I expect it to make a set once property, but I could have some non deterministic logic in the getter that I don‘t want to loose.

With accessors we have two different choices here (correct me if I’m wrong please):

  1. consider decorators as property descriptors decorators and therefore giving the decorators ‘full control’ over the decoration process, or
  2. consider decorators as function decorators and therefore giving the user control on what happens where.

Back to @RunOnce, in case 1 it would have no meaning on accessors because it would apply the effect (“it runs once”) on the property value (dynamic or not), while on case 2 the user could choose do decorate an accessor.

yuchi avatar Mar 14 '15 23:03 yuchi

An (after)thought: a simple, unobtrusive flag could do the job but would bring confusion over the usage of decorators.

function Decorator(target, name, descriptor, type) {
  // type here is one of [ 'property', 'set', 'get' ]
}

Also it would have no standard way of driving where the application have to happen:

class Person {
 @RunOnce // run once what? the getter? or the returned function?
 get invoker() {
  return function () {}
 }
}

yuchi avatar Mar 14 '15 23:03 yuchi

@yuchi @wycats AFAIK this is the only valid issue here from 2015. Distinguishing between use cases, i.e. did one decorate the getter or the setter. But I think that this is being addressed with the upcoming spec?

And if not, this should definitely be part of the spec, namely that one can use different decorators on either setter or getter without each of them being decorated by the same set of decorators.

silkentrance avatar Feb 28 '16 23:02 silkentrance