-
Notifications
You must be signed in to change notification settings - Fork 319
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
getter/setter pairs should be available in extensions #286
Comments
This looks at least somewhat unintentional, and can be fixed.
|
I took a brief look at this a bit ago and ran into the problem that @kevinpschaaf describes at the end of (2). The brief change I explored is documented at https://github.com/silenceisgolden/lit-element/commit/eb9324ed302e5332a75eecb044be11ec4fecc11e. I think if the rule is adopted that generated accessors will never overwrite existing accessors this might be a non-obvious limitation. The fix I worked on broke other tests that are expecting the accessor to be overwritten, and that does carry some logic. Separate from the context of custom elements, you can extend getters and setters if you wire up the super calls correct, as shown at https://glitch.com/edit/#!/surf-rise?path=script.js:44:52. I would be curious to know your thoughts on if people understand getter/setter extension in plain ole' JS that they might expect Thanks for prioritizing this for 1.0! |
@silenceisgolden Yeah definitely good insight, thanks for bringing it up. We've definitely considered all of this in the past, and it gets fairly complicated. As you say, In addition, we've also considered supporting "supering" to the generated accessors in the past. Conceptually it seems reasonable that a user might want to install a setter on a class and then decide to run the generated accessor or not (in the same way one might want to do from a subclass via super), however since the generated accessors need to be installed on the same prototype as the user's accessor, a super call wouldn't work. So then it's back to a custom rule about how existing accessors are wrapped or not and the semantics of that, and it starts to feel leaky again. We'll try to get a few more opinions and try to come to a resolution on this. Thanks. |
This is a bit tricky. We toyed with the idea of automatically wrapping a user's getter/setter previously, but decided against it. The problem is that it's not really possible for the library to know if wrapping a user's getter/setter is actually what's desirable. Instead, I think we want to keep the accessor generation system as simple as we can and encourage users to create their own accessors when this type of more complex composition is needed. For (2) above, the issue is that we do want a subclass to be able to override the property options (e.g. |
Thanks for the responses, I appreciate the context. One more thing I'll leave here is the question of if it would even make sense to add a property to Cheers |
Fixes #286. * Only processes properties expicitly defined on the class. This avoids double work since properties are inherited. * We now also avoid creating a property if the property already exists anywhere in the element's prototype chain. Previously, this was an `ownProperty` check. * This also removes the optimization of taking the property options from the closure where the property is defined. This allows subclasses to redefine property options without needing to redefine the accessor. * Finally, also removes the private `_requestPropertyUpdate` which would be superfluous with this change.
For now, we landed on simply never stomping on a user's accessor. I think we can potentially revisit the idea of adding a property option for We've removed the optimization of storing the property options in the closure for the generated setter. This ensures any subclass can override property options easily. The properties system really does 2 very different things:
|
Just like to point one caveat that is not clear in the docs:
The example below will not work: class MyElement extends LitElement {
get mood() { return this._mood; }
set mood(mood) { this._mood = mood; this.requestUpdate(); }
render() {
return html`<style> .mood { color: green; } </style>
Web Components are <span class="mood">${this.mood}</span>!`;
}
}
customElements.define('my-element', MyElement);
//later
let mood = 'great' // -> if var mood is changed and template executed again no update occurs
html`<my-element .mood=${mood}></my-element>` This falls because lit-html sets the mood property in the own instance before the custom element is upgraded shadowing the setter |
We iterated on the solution here a little bit, and actually ended up landing on something I straw-manned in my comment above:
We achieved this by adding a couple fast-paths to ensure extra work required to create the accessor and handle potentially multiple calls to This should handle composition better, and also removes the need for users to call |
@blikblum Acknowledged, we can improve the docs here to ensure users understand that inclusion in |
This sounds excellent but for 2 questions: If a superclass has a Will a user still need to include a requestUpdate call if they change a different property in the setter? Let's say:
Many thanks |
@silenceisgolden Right, so the new rule will be, if the property is listed in In the example above, since That said, it's unclear if that was a contrived example or not, but if your actual goal is to set updated(changedProperties) {
if (changedProperties.has('disabled')) {
if (this.disabled) {
this.setAttribute('aria-disabled', 'true');
} else {
this.removeAttribute('aria-disabled');
}
}
} |
* Ensure user accessor is never overridden Fixes #286. * Only processes properties expicitly defined on the class. This avoids double work since properties are inherited. * We now also avoid creating a property if the property already exists anywhere in the element's prototype chain. Previously, this was an `ownProperty` check. * This also removes the optimization of taking the property options from the closure where the property is defined. This allows subclasses to redefine property options without needing to redefine the accessor. * Finally, also removes the private `_requestPropertyUpdate` which would be superfluous with this change. * Update changelog and format. * Upgrade to latest wcjs * Http-->https changes to package-lock (?) * Add user accessor wrapping and fix Symbol polyfill issue. * Add semicolons. * Test updates based on review. * Format.
Note that while the originally reported issue (LitElement incorrectly re-creating accessor over top of superclass's custom accessor despite the subclass not declaring the property), we have since reverted the change in #359 that added "accessor wrapping." The rationale is that we want to align the property metaprogramming as closely as possible to the new class field semantics (especially since we expect That said, we've retained the See #454 for more details. |
Description
When extending a class with getter/setter controlled property management, these effects should persist in child extensions.
Live Demo
https://glitch.com/edit/#!/nervous-columnist?path=index.html:24:0
If you open you console, you should see a log of
parent
and one ofchild
but the second log is missing.Steps to Reproduce
mood
attribute to property relationship.mood
.Expected Results
Getter/Setter works.
Actual Results
Getter/Setter is ignored... 😢
Browsers Affected
Versions
The text was updated successfully, but these errors were encountered: