Skip to content
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

Don't throw the shadowed properties dev-mode error when a property is intentionally not reactive. #2160

Merged
merged 13 commits into from
Oct 14, 2021

Conversation

bicknellr
Copy link
Member

This PR prevents the dev-mode error about shadowed properties from being thrown if the property is configured not to have a generated descriptor. This includes setting noAccessor in the properties block / @property decorator and returning undefined from getPropertyDescriptor.

This PR also adds undefined as a possible return type for getPropertyDescriptor, which is documented as if it should be able to do this, but currently isn't allowed due to the inferred return type. This change required adding a few ! assertions in some existing tests.

@google-cla google-cla bot added the cla: yes label Sep 14, 2021
@github-actions
Copy link
Contributor

github-actions bot commented Sep 14, 2021

📊 Tachometer Benchmark Results

Summary

⏳ Benchmarks are currently running. Results below are out of date.

nop-update

  • lit-html-kitchen-sink: unsure 🔍 -1% - +1% (-0.40ms - +0.32ms)
    this-change vs tip-of-tree

render

  • lit-element-list: unsure 🔍 -1% - +0% (-0.80ms - +0.25ms)
    this-change vs tip-of-tree
  • lit-html-kitchen-sink: faster ✔ 0% - 1% (0.03ms - 0.33ms)
    this-change vs tip-of-tree
  • lit-html-repeat: unsure 🔍 -2% - +2% (-0.21ms - +0.19ms)
    this-change vs tip-of-tree
  • lit-html-template-heavy: unsure 🔍 -0% - +2% (-0.27ms - +1.20ms)
    this-change vs tip-of-tree
  • reactive-element-list: unsure 🔍 -1% - +2% (-0.45ms - +1.12ms)
    this-change vs tip-of-tree

update

  • lit-element-list: unsure 🔍 -2% - +1% (-16.81ms - +7.66ms)
    this-change vs tip-of-tree
  • lit-html-kitchen-sink: unsure 🔍 -2% - +2% (-1.76ms - +1.65ms)
    this-change vs tip-of-tree
  • lit-html-repeat: unsure 🔍 -2% - +1% (-5.44ms - +4.80ms)
    this-change vs tip-of-tree
  • lit-html-template-heavy: unsure 🔍 -1% - +2% (-1.52ms - +2.18ms)
    this-change vs tip-of-tree
  • reactive-element-list: unsure 🔍 -1% - +2% (-7.58ms - +14.93ms)
    this-change vs tip-of-tree

update-reflect

  • lit-element-list: unsure 🔍 -2% - +1% (-16.58ms - +9.11ms)
    this-change vs tip-of-tree
  • reactive-element-list: unsure 🔍 -2% - +1% (-15.32ms - +11.15ms)
    this-change vs tip-of-tree

Results

⏳ Benchmarks are currently running. Results below are out of date.
lit-element-list

render

VersionAvg timevs this-change
vs tip-of-tree
tip-of-tree
vs previous-release
previous-release
this-change
86.80ms - 87.56ms-unsure 🔍
-1% - +0%
-0.80ms - +0.25ms
faster ✔
19% - 20%
20.28ms - 21.36ms
tip-of-tree
tip-of-tree
87.10ms - 87.82msunsure 🔍
-0% - +1%
-0.25ms - +0.80ms
-faster ✔
19% - 19%
20.02ms - 21.07ms
previous-release
previous-release
107.62ms - 108.38msslower ❌
23% - 25%
20.28ms - 21.36ms
slower ❌
23% - 24%
20.02ms - 21.07ms
-

update

VersionAvg timevs this-change
vs tip-of-tree
tip-of-tree
vs previous-release
previous-release
this-change
712.68ms - 729.57ms-unsure 🔍
-2% - +1%
-16.81ms - +7.66ms
faster ✔
7% - 10%
57.93ms - 81.94ms
tip-of-tree
tip-of-tree
716.85ms - 734.55msunsure 🔍
-1% - +2%
-7.66ms - +16.81ms
-faster ✔
7% - 10%
53.07ms - 77.66ms
previous-release
previous-release
782.53ms - 799.60msslower ❌
8% - 11%
57.93ms - 81.94ms
slower ❌
7% - 11%
53.07ms - 77.66ms
-

update-reflect

VersionAvg timevs this-change
vs tip-of-tree
tip-of-tree
vs previous-release
previous-release
this-change
760.30ms - 778.18ms-unsure 🔍
-2% - +1%
-16.58ms - +9.11ms
faster ✔
4% - 7%
28.84ms - 53.73ms
tip-of-tree
tip-of-tree
763.76ms - 782.20msunsure 🔍
-1% - +2%
-9.11ms - +16.58ms
-faster ✔
3% - 6%
24.90ms - 50.20ms
previous-release
previous-release
801.86ms - 819.19msslower ❌
4% - 7%
28.84ms - 53.73ms
slower ❌
3% - 7%
24.90ms - 50.20ms
-
lit-html-kitchen-sink

render

VersionAvg timevs this-change
vs tip-of-tree
tip-of-tree
vs previous-release
previous-release
this-change
35.59ms - 35.78ms-faster ✔
0% - 1%
0.03ms - 0.33ms
faster ✔
16% - 17%
6.55ms - 7.34ms
tip-of-tree
tip-of-tree
35.75ms - 35.97msslower ❌
0% - 1%
0.03ms - 0.33ms
-faster ✔
15% - 17%
6.36ms - 7.16ms
previous-release
previous-release
42.24ms - 43.01msslower ❌
18% - 21%
6.55ms - 7.34ms
slower ❌
18% - 20%
6.36ms - 7.16ms
-

update

VersionAvg timevs this-change
vs tip-of-tree
tip-of-tree
vs previous-release
previous-release
this-change
86.65ms - 89.55ms-unsure 🔍
-2% - +2%
-1.76ms - +1.65ms
faster ✔
4% - 8%
3.38ms - 7.19ms
tip-of-tree
tip-of-tree
87.25ms - 89.05msunsure 🔍
-2% - +2%
-1.65ms - +1.76ms
-faster ✔
4% - 7%
3.71ms - 6.75ms
previous-release
previous-release
92.15ms - 94.61msslower ❌
4% - 8%
3.38ms - 7.19ms
slower ❌
4% - 8%
3.71ms - 6.75ms
-

nop-update

VersionAvg timevs this-change
vs tip-of-tree
tip-of-tree
vs previous-release
previous-release
this-change
29.41ms - 29.97ms-unsure 🔍
-1% - +1%
-0.40ms - +0.32ms
unsure 🔍
-3% - +0%
-0.93ms - +0.15ms
tip-of-tree
tip-of-tree
29.50ms - 29.95msunsure 🔍
-1% - +1%
-0.32ms - +0.40ms
-unsure 🔍
-3% - +1%
-0.87ms - +0.16ms
previous-release
previous-release
29.61ms - 30.54msunsure 🔍
-1% - +3%
-0.15ms - +0.93ms
unsure 🔍
-1% - +3%
-0.16ms - +0.87ms
-
lit-html-repeat

render

VersionAvg timevs this-change
vs tip-of-tree
tip-of-tree
vs previous-release
previous-release
this-change
12.64ms - 12.91ms-unsure 🔍
-2% - +2%
-0.21ms - +0.19ms
faster ✔
6% - 8%
0.81ms - 1.10ms
tip-of-tree
tip-of-tree
12.64ms - 12.93msunsure 🔍
-2% - +2%
-0.19ms - +0.21ms
-faster ✔
6% - 8%
0.79ms - 1.11ms
previous-release
previous-release
13.68ms - 13.78msslower ❌
6% - 9%
0.81ms - 1.10ms
slower ❌
6% - 9%
0.79ms - 1.11ms
-

update

VersionAvg timevs this-change
vs tip-of-tree
tip-of-tree
vs previous-release
previous-release
this-change
358.06ms - 363.36ms-unsure 🔍
-2% - +1%
-5.44ms - +4.80ms
faster ✔
28% - 30%
143.03ms - 153.45ms
tip-of-tree
tip-of-tree
356.65ms - 365.40msunsure 🔍
-1% - +2%
-4.80ms - +5.44ms
-faster ✔
28% - 30%
141.65ms - 154.19ms
previous-release
previous-release
504.46ms - 513.44msslower ❌
39% - 43%
143.03ms - 153.45ms
slower ❌
39% - 43%
141.65ms - 154.19ms
-
lit-html-template-heavy

render

VersionAvg timevs this-change
vs tip-of-tree
tip-of-tree
vs previous-release
previous-release
this-change
58.20ms - 59.46ms-unsure 🔍
-0% - +2%
-0.27ms - +1.20ms
faster ✔
16% - 18%
11.63ms - 13.08ms
tip-of-tree
tip-of-tree
57.98ms - 58.74msunsure 🔍
-2% - +0%
-1.20ms - +0.27ms
-faster ✔
17% - 19%
12.30ms - 13.34ms
previous-release
previous-release
70.82ms - 71.54msslower ❌
20% - 22%
11.63ms - 13.08ms
slower ❌
21% - 23%
12.30ms - 13.34ms
-

update

VersionAvg timevs this-change
vs tip-of-tree
tip-of-tree
vs previous-release
previous-release
this-change
119.85ms - 122.76ms-unsure 🔍
-1% - +2%
-1.52ms - +2.18ms
faster ✔
11% - 14%
15.30ms - 19.19ms
tip-of-tree
tip-of-tree
119.84ms - 122.11msunsure 🔍
-2% - +1%
-2.18ms - +1.52ms
-faster ✔
12% - 14%
15.85ms - 19.29ms
previous-release
previous-release
137.26ms - 139.84msslower ❌
12% - 16%
15.30ms - 19.19ms
slower ❌
13% - 16%
15.85ms - 19.29ms
-
reactive-element-list

render

VersionAvg timevs this-change
vs tip-of-tree
tip-of-tree
vs previous-release
previous-release
this-change
58.95ms - 59.97ms-unsure 🔍
-1% - +2%
-0.45ms - +1.12ms
unsure 🔍
-1% - +1%
-0.68ms - +0.79ms
tip-of-tree
tip-of-tree
58.53ms - 59.72msunsure 🔍
-2% - +1%
-1.12ms - +0.45ms
-unsure 🔍
-2% - +1%
-1.07ms - +0.51ms
previous-release
previous-release
58.88ms - 59.93msunsure 🔍
-1% - +1%
-0.79ms - +0.68ms
unsure 🔍
-1% - +2%
-0.51ms - +1.07ms
-

update

VersionAvg timevs this-change
vs tip-of-tree
tip-of-tree
vs previous-release
previous-release
this-change
712.92ms - 728.88ms-unsure 🔍
-1% - +2%
-7.58ms - +14.93ms
unsure 🔍
-1% - +2%
-5.99ms - +14.48ms
tip-of-tree
tip-of-tree
709.29ms - 725.16msunsure 🔍
-2% - +1%
-14.93ms - +7.58ms
-unsure 🔍
-1% - +2%
-9.63ms - +10.77ms
previous-release
previous-release
710.24ms - 723.06msunsure 🔍
-2% - +1%
-14.48ms - +5.99ms
unsure 🔍
-2% - +1%
-10.77ms - +9.63ms
-

update-reflect

VersionAvg timevs this-change
vs tip-of-tree
tip-of-tree
vs previous-release
previous-release
this-change
791.20ms - 809.35ms-unsure 🔍
-2% - +1%
-15.32ms - +11.15ms
unsure 🔍
-1% - +2%
-11.96ms - +13.30ms
tip-of-tree
tip-of-tree
792.72ms - 812.00msunsure 🔍
-1% - +2%
-11.15ms - +15.32ms
-unsure 🔍
-1% - +2%
-10.28ms - +15.79ms
previous-release
previous-release
790.82ms - 808.38msunsure 🔍
-2% - +1%
-13.30ms - +11.96ms
unsure 🔍
-2% - +1%
-15.79ms - +10.28ms
-

tachometer-reporter-action v2 for Benchmarks

@bicknellr bicknellr marked this pull request as ready for review September 14, 2021 23:21
@@ -3075,4 +3075,95 @@ suite('ReactiveElement', () => {
assert.equal(el2.attrValue, 'custom');
});
});

if (DEV_MODE) {
Copy link
Member

Choose a reason for hiding this comment

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

This should be moved to reactive-element_dev_mode_test

Copy link
Member Author

Choose a reason for hiding this comment

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

Ok, I moved these into that file.

@changeset-bot
Copy link

changeset-bot bot commented Sep 17, 2021

🦋 Changeset detected

Latest commit: ad9043c

The changes in this PR will be included in the next version bump.

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@@ -1140,7 +1153,13 @@ export abstract class ReactiveElement
const shadowedProperties: string[] = [];
(this.constructor as typeof ReactiveElement).elementProperties.forEach(
(_v, p) => {
if (this.hasOwnProperty(p) && !this.__instanceProperties?.has(p)) {
if (
Copy link
Member

Choose a reason for hiding this comment

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

Rather than loop over elementProperties, this can just loop over prototypeToReactivePropertyNames.get(this.constructor.prototype), right?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah, I think you're right: in createProperty, the elementProperties entry is always set before the prototypeToReactivePropertyNames entry might be set, so prototypeToReactivePropertyNames should always be the subset we want here. Updated.

@kevinpschaaf kevinpschaaf added this to the Lit RC.5 milestone Sep 20, 2021
@justinfagnani justinfagnani modified the milestones: Lit 2.0, Lit 2.1 Sep 21, 2021
const reactivePropertyNames =
prototypeToReactivePropertyNames.get(this.prototype) ?? new Set();
reactivePropertyNames.add(name);
prototypeToReactivePropertyNames.set(
Copy link
Member

Choose a reason for hiding this comment

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

I don't think this will catch the case of shadowing a property defined in the superclass. We can probably just copy the superclass set of properties when the set is created.

e.g. something like new Set(prototypeToReactivePropertyNames.get(this.prototype.prototype))

We should add a test for that as well.

Copy link
Member Author

Choose a reason for hiding this comment

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

I've added a test for the case where a property defined by some ancestor class would be shadowed by a class field. Also, I had to move the initialization of this set into finalize so that the set will always exist, even if that class doesn't define any properties itself.

Copy link
Member Author

@bicknellr bicknellr Oct 12, 2021

Choose a reason for hiding this comment

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

There's one thing I was confused about when moving the initialization: why is it safe to assume that the parent class is something with a finalize function? Wouldn't it eventually try to call finalize on HTMLElement?

It seems like I need to update this initialization to handle this case, but the surrounding code doesn't seem to need to do that. Pretty sure that it's currently lucking out on my probably-incorrect use of ! in that new Set(undefined) happens to produce an empty set.

@@ -644,6 +652,17 @@ export abstract class ReactiveElement
this.elementProperties = new Map(superCtor.elementProperties);
// initialize Map populated in observedAttributes
this.__attributeToPropertyMap = new Map();
if (DEV_MODE) {
Copy link
Member

Choose a reason for hiding this comment

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

I'd rather this be in createProperty just to keep the DEV_MODE code less spread out.

Copy link
Member Author

Choose a reason for hiding this comment

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

I moved this here to avoid walking the prototype chain because createProperty isn't guaranteed to be called at least once for each class. Is walking it preferable to splitting these?

Copy link
Member Author

@bicknellr bicknellr Oct 12, 2021

Choose a reason for hiding this comment

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

Also, I'm not sure when that would imply combining the list for classes where ancestors define the properties and some tail portion of the hierarchy prevents those properties from being reactive without themselves defining any properties. (The throws when reactive properties defined by an ancestor class are shadowed by class fields test is the smallest example of this.)

Copy link
Member

Choose a reason for hiding this comment

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

Good point. What about storing the set on the prototype rather than looking it up in the map. That way you'll get it on whatever superclass has it?

Copy link
Member Author

Choose a reason for hiding this comment

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

Ok, I moved the set initialization back into createProperty and make the class create a new one if it doesn't have its own.

@bicknellr bicknellr merged commit 90a8c12 into main Oct 14, 2021
@bicknellr bicknellr deleted the shadowed-properties-check branch October 14, 2021 22:33
@github-actions github-actions bot mentioned this pull request Nov 9, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants