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

Fix compatibility with JSC static property optimizations #735

Merged
merged 5 commits into from
Jul 16, 2019
Merged

Conversation

aomarks
Copy link
Member

@aomarks aomarks commented Jul 15, 2019

Fixes #732

/**
* Marks class as having finished creating properties.
*/
const finalized = new Set<typeof UpdatingElement>();

Choose a reason for hiding this comment

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

Wouldn't a WeakSet be better here? As is, this'll strongly hold onto every LitElement.

Copy link
Contributor

Choose a reason for hiding this comment

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

This would only hold on to class definitions (typeof UpdatingElement). But also, @aomarks is changing the PR to use a property again, just with the index operator and string literal to avoid Closure's bug. That'll allow the GC to collect classes if they every become freeable.

Choose a reason for hiding this comment

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

Ah, I missed the static keyword in the code. 👍

@@ -85,7 +79,11 @@ export class LitElement extends UpdatingElement {

/** @nocollapse */
protected static finalize() {
super.finalize();
if (this !== LitElement) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Add a comment about this if statement.

Is it to match the previous finalized = true behavior?

Copy link
Member Author

@aomarks aomarks Jul 15, 2019

Choose a reason for hiding this comment

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

Yes, done. I didn't want to export the Set from updating-element (to prevent people from depending on that), and now that it's a property, I didn't want to have to know the special string property name outside of updating-element either.

Copy link
Member Author

Choose a reason for hiding this comment

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

(Update: ended up wanting the special name in lit-element.ts after all, since it helps optimize the finalization stack, but I just copied the string instead of exporting something somebody might try and depend on)

* Marks class as having finished creating properties.
* This property was previously used to record the classes that have already
* been finalized. This property is no longer used, but is still declared here
* for backwards compatability in TypeScript typings.
Copy link
Contributor

Choose a reason for hiding this comment

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

IMO breaking TypeScript typings isn't a breaking change for the library.

It would be better for someone to know that the finalized property no longer means anything. In any event, I doubt this will affect anyone, as the finalized property is pretty inside baseball.

Copy link
Member Author

Choose a reason for hiding this comment

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

Fair enough, removed.

@aomarks
Copy link
Member Author

aomarks commented Jul 15, 2019

PTAL @justinfagnani @rictic. We now use a string property instead of a Set, and (from discussion with @justinfagnani) I also moved the finalized check before recursing, instead of after, which optimizes out unnecessary super calls.

Also moves the finalized check earlier, which optimizes out unnecessary
super calls.
/**
* The Closure JS Compiler doesn't currently have good support for static
* propertiy semantics where "this" is dynamic, so we use this hack to bypass
* any rewriting by the compiler.
Copy link
Contributor

Choose a reason for hiding this comment

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

Link to Closure bug

Copy link
Member Author

Choose a reason for hiding this comment

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

There's no one bug for this right now.

Copy link
Member Author

Choose a reason for hiding this comment

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

Added one of them.

@@ -85,7 +79,9 @@ export class LitElement extends UpdatingElement {

/** @nocollapse */
protected static finalize() {
super.finalize();
// The Closure JS Compiler does not always preserve the correct "this"
// when calling static super methods, so explicitly bind here.
Copy link
Contributor

Choose a reason for hiding this comment

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

Link to Closure bug

Copy link
Member Author

Choose a reason for hiding this comment

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

Done.

* propertiy semantics where "this" is dynamic, so we use this hack to bypass
* any rewriting by the compiler.
*/
const finalized = '__finalized__';
Copy link
Contributor

Choose a reason for hiding this comment

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

Hm, if we're going this approach, I think we could do something like the following:

const finalized = 'finalized';

class UpdateElement {
  protected static [finalized] = false;
  protected static finalize() {
    this[finalized] = true;
    // ...
  }
}

Copy link
Member Author

Choose a reason for hiding this comment

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

Done.

super.finalize();
// The Closure JS Compiler does not always preserve the correct "this"
// when calling static super methods, so explicitly bind here.
super.finalize.apply(this);

Choose a reason for hiding this comment

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

Nit: call, since we don't need to pass parameters?

Copy link
Member Author

Choose a reason for hiding this comment

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

Good call

@aomarks aomarks merged commit 601f93f into master Jul 16, 2019
@aomarks aomarks deleted the static branch July 16, 2019 03:28
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.

LitElement sub-optimal/broken with ES5 JSC compilation
5 participants