Skip to content

v3.4.0 release notes and commit list #5644

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 14 commits into from
Apr 27, 2020
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
197 changes: 197 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,202 @@
# Change Log

## Unreleased

### New global settings

This update to Polymer includes some new [global settings](https://polymer-library.polymer-project.org/3.0/docs/devguide/settings):

- `legacyUndefined` / `setLegacyUndefined`

**What does it do?** This setting reverts how computed properties handle `undefined` values to the Polymer 1 behavior: when enabled, computed properties will only be recomputed if none of their dependencies are `undefined`.

Components can override the global setting by setting their `_overrideLegacyUndefined` property to `true`. This is useful for reenabling the default behavior as you migrate individual components:

```js
import {PolymerElement, html} from '@polymer/polymer/polymer-element.js';

class MigratedElement extends PolymerElement { /* ... */ }

// All MigratedElement instances will use the default behavior.
MigratedElement.prototype._overrideLegacyUndefined = true;

customElements.define('migrated-element', SomeElement);
```

**Should I use it?** This setting should only be used for migrating legacy codebases that depend on this behavior and is otherwise **not recommended**.

- `legacyWarnings` / `setLegacyWarnings`

**What does it do?** This setting causes Polymer to warn if a component's template contains bindings to properties that are not listed in that element's [`properties` block](https://polymer-library.polymer-project.org/3.0/docs/devguide/properties). For example:

```js
import {PolymerElement, html} from '@polymer/polymer/polymer-element.js';

class SomeElement extends PolymerElement {
static get template() {
return html`<span>[[someProperty]] is used here</span>`;
}

static get properties() {
return { /* but `someProperty` is not declared here */ };
}
}

customElements.define('some-element', SomeElement);
```

Only properties explicitly declared in the `properties` block are [associated with an attribute](https://polymer-library.polymer-project.org/3.0/docs/devguide/properties#property-name-mapping) and [update when that attribute changes](https://polymer-library.polymer-project.org/3.0/docs/devguide/properties#attribute-deserialization). Enabling this setting will show you where you might have forgotten to declare properties.

**Should I use it?** Consider using this feature during development but don't enable it in production.

- `orderedComputed` / `setOrderedComputed`

**What does it do?** This setting causes Polymer to topologically sort each component's computed properties graph when the class is initialized and uses that order whenever computed properties are run.

For example:

```js
import {PolymerElement, html} from '@polymer/polymer/polymer-element.js';

class SomeElement extends PolymerElement {
static get properties() {
return {
a: {type: Number, value: 0},
b: {type: Number, computed: 'computeB(a)'},
c: {type: Number, computed: 'computeC(a, b)'},
};
}

computeB(a) {
console.log('Computing b...');
return a + 1;
}

computeC(a, b) {
console.log('Computing c...');
return (a + b) * 2;
}
}

customElements.define('some-element', SomeElement);
```

When `a` changes, Polymer's default behavior does not specify the order in which its dependents will run. Given that both `b` and `c` depend directly on `a`, one of two possible orders could occur: [`computeB`, `computeC`] or [`computeC`, `computeB`].

- In the first case - [`computeB`, `computeC`] - `computeB` is run with the new value of `a` and produces a new value for `b`. Then, `computeC` is run with both the new values of `a` and `b` to produce `c`.

- In the second case - [`computeC`, `computeB`] - `computeC` is run first with the new value of `a` and the _current_ value of `b` to produce `c`. Then, `computeB` is run with the new value of `a` to produce `b`. If `computeB` changed the value of `b` then `computeC` will be run again, with the new values of both `a` and `b` to produce the final value of `c`.

However, with `orderedComputed` enabled, the computed properties would have been previously sorted into [`computeB`, `computeC`], so updating `a` would cause them to run specifically in that order.

If your component's computed property graph contains cycles, the order in which they are run when using `orderedComputed` is still undefined.

**Should I use it?** The value of this setting depends on how your computed property functions are implemented. If they are pure and relatively inexpensive, you shouldn't need to enable this feature. If they have side effects that would make the order in which they are run important or are expensive enough that it would be a problem to run them multiple times for a property update, consider enabling it.

- `fastDomIf` / `setFastDomIf`

**What does it do?** This setting enables a different implementation of `<dom-if>` that uses its host element's template stamping facilities (provided as part of `PolymerElement`) rather than including its own. This setting can help with performance but comes with a few caveats:

- First, `fastDomIf` requires that every `<dom-if>` is in the shadow root of a Polymer element: you can't use a `<dom-if>` directly in the main document or inside a shadow root of an element that doesn't extend `PolymerElement`.

- Second, because the `fastDomIf` implementation of `<dom-if>` doesn't include its own template stamping features, it doesn't create its own scope for property effects. This means that any properties you were previously setting on the `<dom-if>` will no longer be applied within its template, only properties of the host element are available.

**Should I use it?** This setting is recommended as long as your app doesn't use `<dom-if>` as described in the section above.

- `removeNestedTemplates` / `setRemoveNestedTemplates`

**What does it do?** This setting causes Polymer to remove the child `<template>` elements used by `<dom-if>` and `<dom-repeat>` from the their containing templates. This can improve the performance of cloning your component's template when new instances are created.

**Should I use it?** This setting is generally recommended.

- `suppressTemplateNotifications` / `setSuppressTemplateNotifications`

**What does it do?** This setting causes `<dom-if>` and `<dom-repeat>` not to dispatch `dom-change` events when their rendered content is updated. If you're using lots of `<dom-if>` and `<dom-repeat>` but not listening for these events, this setting lets you disable them and their associated dispatch work.

You can override the global setting for an individual `<dom-if>` or `<dom-repeat>` by setting its `notify-dom-change` boolean attribute:

```js
import {PolymerElement, html} from '@polymer/polymer/polymer-element.js';

class SomeElement extends PolymerElement {
static get properties() {
return {
visible: {type: Boolean, value: false},
};
}

static get template() {
return html`
<button on-click="_toggle">Toggle</button>
<!-- Set notify-dom-change to enable dom-change events for this particular <dom-if>. -->
<dom-if if="[[visible]]" notify-dom-change on-dom-change="_onDomChange">
<template>
Hello!
</template>
</dom-if>
`;
}

_toggle() {
this.visible = !this.visible;
}

_onDomChange(e) {
console.log("Received 'dom-change' event.");
}
}

customElements.define('some-element', SomeElement);
```

**Should I use it?** This setting is generally recommended.

- `legacyNoObservedAttributes` / `setLegacyNoObservedAttributes`

**What does it do?** This setting causes `LegacyElementMixin` not to use the browser's built-in mechanism for informing elements of attribute changes (i.e. `observedAttributes` and `attributeChangedCallback`), which lets Polymer skip computing the list of attributes it tells the browser to observe. Instead, `LegacyElementMixin` simulates this behavior by overriding attribute APIs on the element and calling `attributeChangedCallback` itself.

This setting has similar API restrictions to those of the [custom elements polyfill](https://github.com/webcomponents/polyfills/tree/master/packages/custom-elements). You should only use the element's `setAttribute` and `removeAttribute` methods to modify attributes: using (e.g.) the element's `attributes` property to modify its attributes is not supported with `legacyNoObservedAttributes` and won't properly trigger `attributeChangedCallback` or any property effects.

Components can override the global setting by setting their `_legacyForceObservedAttributes` property to `true`. This property's effects occur at startup; it won't have any effect if modified at runtime and should be set in the class definition.

**Should I use it?** This setting should only be used if startup time is significantly affected by Polymer's class initialization work - for example, if you have a large number of components being loaded but are only instantiating a small subset of them. Otherwise, this setting is **not recommended**.

- `useAdoptedStyleSheetsWithBuiltCSS` / `setUseAdoptedStyleSheetsWithBuiltCSS`

**What does it do?** If your application is uses [pre-built Shady CSS styles](https://github.com/polymer/polymer-css-build) and your browser supports [constructable stylesheet objects](https://wicg.github.io/construct-stylesheets/), this setting will cause Polymer to extract all `<style>` elements from your components' templates, join them into a single stylesheet, and share this stylesheet with all instances of the component using their shadow roots' [`adoptedStyleSheets`](https://wicg.github.io/construct-stylesheets/#dom-documentorshadowroot-adoptedstylesheets) array. This setting may improve your components' memory usage and performance depending on how many instances you create and how large their style sheets are.

**Should I use it?** Consider using this setting if your app already uses pre-built Shady CSS styles. Note that position-dependent CSS selectors (e.g. containing `:nth-child()`) may become unreliable for siblings of your components' styles as a result of runtime-detected browser support determining if styles are removed from your components' shadow roots.

### Other new features

#### `<dom-repeat>`

- `reuseChunkedInstances`

**What does it do?** This boolean property causes `<dom-repeat>` to reuse template instances even when `items` is replaced with a new array, matching the Polymer 1 behavior.

By default, a `<dom-repeat>` with chunking enabled (i.e. `initialCount` >= 0) will drop all previously rendered template instances and create new ones whenever the `items` array is replaced. With `reuseChunkedInstances` set, any previously rendered template instances will instead be repopulated with data from the new array before new instances are created.

**Should I use it?** This flag is generally recommended and can improve rendering performance of chunked `<dom-repeat>` instances with live data.

#### `LegacyElementMixin`

- `disable-upgrade`

**What does it do?** `LegacyElementMixin` now has built-in support for the `disable-upgrade` attribute (usually provided by [`DisableUpgradeMixin`](https://polymer-library.polymer-project.org/3.0/api/mixins/disable-upgrade-mixin)) that becomes active when the global `legacyOptimizations` setting is enabled, matching the Polymer 1 behavior.

**Should I use it?** Consider using this setting if you are already using the `legacyOptimizations` setting and migrating older components that depend on `disable-upgrade` without explicit application of `DisableUpgradeMixin`.

### Bug fixes

#### `<dom-repeat>`

- Chunking behavior

`<dom-repeat>` no longer resets the number of rendered instances to `initialCount` when modifying `items` with `PolymerElement`'s array modification methods ([`splice`](https://polymer-library.polymer-project.org/3.0/api/mixins/element-mixin#ElementMixin-method-splice), [`push`](https://polymer-library.polymer-project.org/3.0/api/mixins/element-mixin#ElementMixin-method-push), etc.). The number of rendered instances will only be reset to `initialCount` if the `items` array itself is replaced with a new array object.

See [#5631](https://github.com/Polymer/polymer/issues/5631) for more information.

## [v3.3.1](https://github.com/Polymer/polymer/tree/v3.3.1) (2019-11-08)
- [ci skip] bump to 3.3.1 ([commit](https://github.com/Polymer/polymer/commit/11f1f139))

Expand Down
6 changes: 0 additions & 6 deletions externs/polymer-externs.js
Original file line number Diff line number Diff line change
Expand Up @@ -138,15 +138,9 @@ Polymer.syncInitialRender;
/** @type {boolean} */
Polymer.legacyUndefined;

/** @type {boolean} */
Polymer.legacyNoBatch;

/** @type {boolean} */
Polymer.legacyWarnings;

/** @type {boolean} */
Polymer.legacyNotifyOrder;

/** @type {boolean} */
Polymer.orderedComputed;

Expand Down