Skip to content

Prevent element property set from throwing errors for readonly properties. #3687

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

Merged
merged 1 commit into from
Oct 11, 2019

Conversation

pngwn
Copy link
Member

@pngwn pngwn commented Oct 11, 2019

Fixes #3681.

When spreading props we were previously doing a key in obj check when deciding to assign to the property or set the attribute. This fails when the property exists but the setter is undefined which is the case with some (all?) read-only properties.

This PR changes that behaviour and instead uses Object.getOwnPropertyDescriptor(el.__proto__, key) and, if it exists, checks that the set property exists as well. It is important to provide two checks, one for the descriptors (or the key itself) and one for the actual set property of the descriptor, to prevent throwing errors when trying to access set of undefined.

I also needed to add //@ts-ignore when accessing node.__proto__ since the TS people don't think valid properties should be on the node interface if they are deprecated.

} else if (key in node) {
} else if (
//@ts-ignore
(a = Object.getOwnPropertyDescriptor(node.__proto__, key)) && a.set
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It feels like it would be faster to just do const descriptors = Object.getOwnPropertyDescriptors(node.__proto__) once and then do descriptors[key] && descriptors[key].set here, but I don't actually have any data to back this up.

Copy link
Member Author

@pngwn pngwn Oct 11, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe you can't trust benchmarks but at least this supports your hunch, which makes sense to me. I certainly can't imagine it being any slower.

@pngwn pngwn force-pushed the 3681-readonly-element-props branch 2 times, most recently from 86f2f57 to c65e9fd Compare October 11, 2019 15:59
@Conduitry
Copy link
Member

Can you add an entry under 'unreleased' in the changelog for this? I'm trying to start a thing where PRs from maintainers include that - and where maintainers will update the changelog right after merging something from a non-maintainer - so that cutting the release later is less of a hassle.

@@ -90,10 +90,12 @@ export function attr(node: Element, attribute: string, value?: string) {
}

export function set_attributes(node: Element & ElementCSSInlineStyle, attributes: { [x: string]: string }) {
//@ts-ignore
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Extreme nit zone: Every other place where we have @ts-ignore, there's a space after the //.

@pngwn
Copy link
Member Author

pngwn commented Oct 11, 2019

That's no problem, I'll sort these issues out shortly and squish them down.

@pngwn pngwn force-pushed the 3681-readonly-element-props branch from c65e9fd to 712f85a Compare October 11, 2019 21:49
@pngwn
Copy link
Member Author

pngwn commented Oct 11, 2019

If you're happy with the changelog entry, this should be ready now.

@Conduitry
Copy link
Member

What typically has been happening was linking to the original issues in the changelog when possible rather than to the pull requests.

@pngwn pngwn force-pushed the 3681-readonly-element-props branch from 712f85a to 72d2c01 Compare October 11, 2019 21:55
@pngwn
Copy link
Member Author

pngwn commented Oct 11, 2019

Ah right, okay. They're 50 / 50, so I wasn't sure. Fixed now.

@Conduitry Conduitry merged commit 57aeddc into sveltejs:master Oct 11, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Spread operator doesn't work with "form" and "list" attributes
2 participants