-
Notifications
You must be signed in to change notification settings - Fork 2k
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
2.x - Performance optimizations geared towards legacy Polymer({...})
use
#5418
Conversation
Set using `Polymer.setLegacyOptimizations(true)`. This flag enables optimizaitons including, always stripping whitespace from templates and avoiding cloning element templates (assumes no inheritance is used) Also re-enables dir-mixin.
* fix issue where registered was called on element instance instead of prototype * fix issue where applyListeners was called in constructor rather than initializeProperties; this made `disable-upgrade` mixin not properly work with litsners.
lib/mixins/element-mixin.html
Outdated
templateStyle.parentNode.insertBefore(s, templateStyle); | ||
} else { | ||
templateStyleIndex++; | ||
if (!window.skipStyleIncludesAndUrls) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rather than putting this on window
, shouldn't we put this in the Polymer.Settings
object?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops, thanks. Going to get this window.ShadyCSS.cssBuild
being set (which will shortly be added to ShadyCSS
.
}); | ||
|
||
test('elements upgrade when `disable-upgrade` removed', function() { | ||
assert.notOk(el.$.disabledEl.hasCreated); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we not remove these assertions or are they regressions? Are they a breaking change for our users?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These were actually duplicate assertions from the previous test (https://github.com/Polymer/polymer/pull/5418/files#diff-ed6f0a354a50488549e9b8ea17788d86R240) that were incorrectly being tested again.
test/unit/mixin-behaviors.html
Outdated
@@ -552,7 +551,13 @@ | |||
}); | |||
|
|||
test('nested-behavior dedups', function() { | |||
assert.equal(el.behaviors.length, 4); | |||
assert.equal(el.behaviors.length, 2); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This also seems like a regression to me. Are we sure users will not run into any breaking changes?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not a regression since the test changed, but the behavior is weird and I think we should change it.
We didn't have a test where Polymer.mixinBehaviors
was called on a legacy element with behaviors (since this is pretty exotic) and this test was just updated to do that.
When that happens, the behaviors list is set to the subclasses' list of behaviors. However, the "active" set of behaviors on the element is the de-duplicated flat list of all behaviors on anything in the prototype chain. Given that, it seems like .behaviors
should be this de-duplicated flattened list of "active" behaviors. We can make that change and update the test.
* Uses `window.ShadyCSS.cssBuild` to avoid doing unnecessary work in `processElementStyles` * Stores the list of active in-use behaviors in a legacy element's `behaviors` property. This only matters in the exotic case when elements with behaviors are extended with more behaviors and previously the list included only the subclasses behaviors (although the element otherwise worked as expected).
Also use exclusively in `properties-mixin`
IE/older Safari require all arguments.
Polymer({...})
usePolymer({...})
use
lib/legacy/class.html
Outdated
GenerateClassFromInfo(b, klass); | ||
function copyBehaviorProperties(behaviors, klass) { | ||
const meta = {}; | ||
const superMeta = klass.prototype.__behaviorMetaProps; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since these are all lifecycle-related, maybe __behaviorCallbacks
would be better than something with "props" in it, since that's sort of overloaded with all the data stuff.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
removed.
lib/legacy/class.html
Outdated
} | ||
|
||
/** | ||
* @return {void} | ||
*/ | ||
created() { | ||
super.created(); | ||
const list = this.__behaviorMetaProps.created; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider adding info. from the base info to the list?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
lib/legacy/class.html
Outdated
mergeProperties(properties, b.properties); | ||
} | ||
} | ||
mergeProperties(properties, info.properties); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seemed like a possible optimization to skip the mergeProperties
step from the base info object into an empty object; it seems superfulous for the initial class -- but then I realized this was required for the computed
to readOnly
coersion and the shorthand type expansion. So that was not intuitive, maybe due to the naming? Suggest different name or at least a comment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added comment.
lib/legacy/class.html
Outdated
klass.prototype.__behaviorMetaProps = meta; | ||
} | ||
|
||
function memoizeBehaviorMetaProps(meta, behavior, superMeta) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's a bug here where the full flattened list of lifecycle callbacks is called once per call to GenerateClassFromInfo
, which happens each time mixinBehaviors
is called.
Instead, store the list of callbacks in the closure for one set of behaviors associated with each call to GenerateClassFromInfo
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed and test added.
lib/legacy/class.html
Outdated
/* NOTE: `beforeRegister` is called here for bc, but the behavior | ||
is different than in 1.x. In 1.0, the method was called *after* | ||
mixing prototypes together but *before* processing of meta-objects. | ||
However, dynamic effects can still be set here and can be done either | ||
in `beforeRegister` or `registered`. It is no longer possible to set | ||
`is` in `beforeRegister` as you could in 1.x. | ||
*/ | ||
const proto = this; | ||
if (proto.hasOwnProperty('__behaviors')) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is just what's in the closure, i.e.
if (behaviors) {
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
lib/legacy/class.html
Outdated
behaviors: true | ||
}, metaProps); | ||
|
||
const memoizedProps = Object.assign({ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Naming of these is confusing. Consider "memoized" --> "filtered"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
@@ -256,11 +256,10 @@ | |||
<script> | |||
HTMLImports.whenReady(function() { | |||
customElements.define('nested-behaviors', | |||
class extends Polymer.mixinBehaviors( | |||
class extends Polymer.mixinBehaviors([window.BehaviorD, window.LifeCycleBehavior1], Polymer.mixinBehaviors( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add assertions for BehaviorD?
Also maybe add a test like const b1 = { ready() {..} };
const b2 = { ready() {..} };
const b3 = { ready() {..} };
const b4 = { ready() {..} };
const sup = Polymer({is: 'sup', behaviors: [b1, b2], ready() {..} })
class sub extends mixinBehaviors([b3,b4], sup) { ready() {..} } And verify that the lifecycle order goes:
|
This ensures it's not called on extendors who do not specifically implement `_registered`. This is important since it's expected to do prototype specific work.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
This better matches what Polymer 1.x did for: * hostAttributes * listeners * properties * observers
…present. This ensures ShadyCSS scoping classes are not removed when a class binding's initial literal value is set.
* ensure element has `is` on prototype early as this is sometimes checked in user code. * ensure properties copied onto elements from info/behaviors are forced to configurable so they can be re-configured by later behaviors. * add `_noAccessors` optimization for faster property copying
Previously, it could be called on a superclass' prototype and not the element's prototype.
* When extended, a behavior `registered` is always called on sub-most prototype rather than the prototype on which `registered` was defined. * behavior property default values are overwritten by later behaviors and elements * readOnly properties ignored when a previous behavior observes the property * observedAttributes when extended
* Don't set up observer in ShadyDOM * Move __activateDir into check instead of replace * skip some tests that never really worked in ShadyDOM
Polymer.legacyOptimizations
flag which avoids copying element templates (needed for subclassing) and turns onstripWhitespace
for all templates.Polymer.telemetry
: now properly records registered elements, even if they have not been created