Skip to content
This repository has been archived by the owner on Sep 29, 2020. It is now read-only.

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

Open
silkentrance opened this issue Apr 3, 2016 · 26 comments

Comments

@silkentrance
Copy link

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
Copy link
Author

@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?

@jayphelps
Copy link
Owner

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?

@silkentrance
Copy link
Author

@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 162bea8#diff-c087668e328e3128ef729aa631ffbd67R79

@silkentrance
Copy link
Author

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

@silkentrance
Copy link
Author

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

@jayphelps
Copy link
Owner

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

@silkentrance what do you mean?

@silkentrance
Copy link
Author

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

@jayphelps
Copy link
Owner

whoops!

@silkentrance
Copy link
Author

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

@jayphelps
Copy link
Owner

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

@silkentrance
Copy link
Author

@jayphelps well it is actually just two extraneous ; 😄

I will implement the required missing tests as well.

@silkentrance
Copy link
Author

@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
Copy link
Author

@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
Copy link
Author

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
Copy link
Author

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.

@jayphelps
Copy link
Owner

@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)

@silkentrance
Copy link
Author

silkentrance commented Apr 17, 2016

@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
Copy link
Author

silkentrance commented Apr 17, 2016

@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
Copy link
Author

@jayphelps see also tc39/proposal-class-public-fields#38 (comment) where I propose a different approach for declaring initialized properties and which might solve existing problems with decorating initialized instance properties.

@jayphelps
Copy link
Owner

@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.

@silkentrance
Copy link
Author

@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.

@jayphelps
Copy link
Owner

@silkentrance what's your email?

@silkentrance
Copy link
Author

@jayphelps I've set it to public now.

@jayphelps
Copy link
Owner

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

image

@silkentrance
Copy link
Author

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

@silkentrance
Copy link
Author

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

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

2 participants