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

extendDescriptor must recursively check super classes/constructors for the first occurrence of 'key'

Open silkentrance opened this issue 9 years ago • 26 comments

https://github.com/jayphelps/core-decorators.js/blob/master/src/extendDescriptor.js#L5

will result in error when deriving from a hierarchy of super classes where the most recently derived from super class does not have the specified own property.

E.g.

class Base
{
   get foo() {return this._foo;}
}

class Foo extends Base
{}

class Bar extends Foo
{
  @extendDescriptor
   set foo(value) {this._foo = 1;}
}

So, rather than just looking for super to have the specified property, it should recursively traverse the inheritance chain instead, returning the first matching own descriptor found.

See https://gist.github.com/silkentrance/21a7016933b0e7d7338f969ba928a457 for a first stab at this problem.

silkentrance avatar Apr 03 '16 14:04 silkentrance

@jayphelps perhaps we should input this to the ongoing discussion about the "final" decorator specification over at @wycats. It seems that one also needs to have access to the constructor function instead of just the prototype, e.g.

decorator({constructor, prototype, attr, descriptor});

where prototype may be undefined in which case the descriptor and attr refer to the constructor instead, aka static properties/methods.

what do you think?

silkentrance avatar Apr 05 '16 21:04 silkentrance

Assuming you have a stereotypically formed class prototype, the constructor is available in decorators still at prototype.constructor. Some of the other decorators use this. Thoughts?

jayphelps avatar Apr 06 '16 05:04 jayphelps

@jayphelps thanks for the clarification, I didn't know that prototype.constructor was available at that time.

As for the implementation, I think that a similar approach to @abstract checking recursively whether it is still abstract should do the trick. See https://github.com/jayphelps/core-decorators.js/pull/51/commits/162bea8d100b544e5c0eb474c2bd75cf8f91c611#diff-c087668e328e3128ef729aa631ffbd67R79

silkentrance avatar Apr 06 '16 21:04 silkentrance

@jayphelps beginning work on a PR for this now...

silkentrance avatar Apr 11 '16 18:04 silkentrance

@jayphelps uh, oh, it seems that the @extendDescriptor are never run... tests are named extendDescriptor.js instead of extendDescriptor.spec.js

silkentrance avatar Apr 11 '16 19:04 silkentrance

uh, oh, it seems that the @extendDescriptor are never run...

@silkentrance what do you mean?

jayphelps avatar Apr 11 '16 19:04 jayphelps

@jayphelps see above... just updated the comment.

silkentrance avatar Apr 11 '16 19:04 silkentrance

whoops!

jayphelps avatar Apr 11 '16 19:04 jayphelps

@jayphelps yikes, do you want to fix the failing tests or should I include that with the PR?

silkentrance avatar Apr 11 '16 19:04 silkentrance

@silkentrance your call. If you don't want to do it I definitely will, just can't right this second

jayphelps avatar Apr 11 '16 19:04 jayphelps

@jayphelps well it is actually just two extraneous ; :smile:

I will implement the required missing tests as well.

silkentrance avatar Apr 11 '16 19:04 silkentrance

@jayphelps initialized properties are difficult in that they will be realized / defined only when the class gets instantiated and there is no superDesc whatsoever unless the instance was created.

Unless the decorator should also work on the instance as well... or, considering static initialized properties, on the class/constructor.

I am dropping support for (static) initialized properties ATM as I cannot find a viable solution for them right now.

And it becomes even more problematic with non configurable initialized properties.

silkentrance avatar Apr 11 '16 20:04 silkentrance

@jayphelps regarding initialized properties: initialized properties will never be defined using Object.defineProperty().

So, this is actually impossible to do, for both initialized static and instance properties.

silkentrance avatar Apr 13 '16 17:04 silkentrance

And the issue with the initialized properties not being defined using Object.defineProperty() might affect other decorators as well... Perhaps, and in that context, decorators are expected to decorate the initializer function only?

silkentrance avatar Apr 13 '16 21:04 silkentrance

It seems that babel5 does not implement initialized properties according to the spec. In the spec it reads that the initialized property should be defined using Object.defineProperty(). Babel5, however, will stop short and just skip the Object.defineProperty() step.

silkentrance avatar Apr 15 '16 20:04 silkentrance

@silkentrance which version of the spec? babel v5 implemented stage-0 spec AFAIK and it has seemed to be correct in regards to initializers from what I can tell, can you clarify? (if you are looking for input, if just documenting your progress feel free to ignore)

jayphelps avatar Apr 16 '16 01:04 jayphelps

@jayphelps Oh, you are right. I did not see that _defineDecoratedPropertyDescriptor() actually calls upon Object.defineProperty(). Thanks for clearing this up.

So we actually do have a special case here. Initialized instance properties will be decorated during design time whereas the property will be defined in the constructor, via _defineDecoratedPropertyDescriptor(), every time that a new instance of the object is created.

So at the time that the decorator is run, it cannot have knowledge of the not yet defined property and it is thus not able to extend the super descriptor.

As for statically defined, initialized properties, they will be defined during construction of the class and there will be a super desc that can be used for extension.

So, what about the single special case? Simply drop the support for it and bail out or silently ignore the fact that one cannot extend the super descriptor that way?

silkentrance avatar Apr 17 '16 14:04 silkentrance

@jayphelps see also the latest version of the PR which will silently ignore the error

However, I still believe this to be a flaw in the spec and the implementation thereof. The properties should be defined on the prototype at design time and not when the instance is created.

silkentrance avatar Apr 17 '16 14:04 silkentrance

@jayphelps see also https://github.com/jeffmo/es-class-fields-and-static-properties/issues/38#issuecomment-214850134 where I propose a different approach for declaring initialized properties and which might solve existing problems with decorating initialized instance properties.

silkentrance avatar Apr 26 '16 19:04 silkentrance

@silkentrance I'm freeing up some time to wrap my head around all these issues here and wycats/javascript-decorators and gonna discuss them with wycats. Will report back.

jayphelps avatar Apr 28 '16 21:04 jayphelps

@jayphelps please invite me to that discussion with wycats when online, I'd like to know and talk about decorators in general, especially about my proposals which might be sound and fair.

silkentrance avatar Apr 29 '16 17:04 silkentrance

@silkentrance what's your email?

jayphelps avatar Apr 30 '16 19:04 jayphelps

@jayphelps I've set it to public now.

silkentrance avatar May 01 '16 06:05 silkentrance

@silkentrance hmm not showing up for me. Can you email me at mine?

image

jayphelps avatar May 01 '16 06:05 jayphelps

@jayphelps send you the address. and it should now show up on the profile, too.

silkentrance avatar May 01 '16 06:05 silkentrance

Is this still an issue, if not, please close.

silkentrance avatar Jul 18 '18 20:07 silkentrance