Skip to content

Commit

Permalink
Ensure styles are not duplicated in ShadowDOM (#481)
Browse files Browse the repository at this point in the history
Fixes #480 by refactoring to avoid the typo that was causing styling to be duplicated when an array was returned from `static get styles`.
  • Loading branch information
Steve Orvell authored and dfreedm committed Jan 25, 2019
1 parent 9c7ea94 commit 2cbe3e0
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 4 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
<!-- ### Fixed -->
## Unreleased

### Fixed
* Fixed a bug causing duplicate styles when an array was returned from `static get styles` ([#480](https://github.com/Polymer/lit-element/issues/480)).

## [2.0.0-rc.4] - 2019-01-24
### Added
* [Maintenance] Added script to publish dev releases automatically ([#476](https://github.com/Polymer/lit-element/pull/476)).
Expand Down
8 changes: 4 additions & 4 deletions src/lit-element.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,23 +89,23 @@ export class LitElement extends UpdatingElement {
// This should be addressed when a browser ships constructable
// stylesheets.
const userStyles = this.styles;
let styles: CSSResult[] = [];
const styles: CSSResult[] = [];
if (Array.isArray(userStyles)) {
styles = flattenStyles(userStyles);
const flatStyles = flattenStyles(userStyles);
// As a performance optimization to avoid duplicated styling that can
// occur especially when composing via subclassing, de-duplicate styles
// preserving the last item in the list. The last item is kept to
// try to preserve cascade order with the assumption that it's most
// important that last added styles override previous styles.
const styleSet = styles.reduceRight((set, s) => {
const styleSet = flatStyles.reduceRight((set, s) => {
set.add(s);
// on IE set.add does not return the set.
return set;
}, new Set<CSSResult>());
// Array.from does not work on Set in IE
styleSet.forEach((v) => styles!.unshift(v));
} else if (userStyles) {
styles = [userStyles];
styles.push(userStyles);
}
return styles;
}
Expand Down
29 changes: 29 additions & 0 deletions src/test/lit-element_styling_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,35 @@ suite('Static get styles', () => {
'3px');
});

// Test this in Shadow DOM without `adoptedStyleSheets` only since it's easily detectable in that case.
const testShadowDOMStyleCount = (!window.ShadyDOM || !window.ShadyDOM.inUse) && !('adoptedStyleSheets' in Document.prototype);
(testShadowDOMStyleCount ? test : test.skip)('when an array is returned from `static get styles`, one style is generated per array item', async () => {
const name = generateElementName();
customElements.define(name, class extends LitElement {
static get styles() {
return [
css`div {
border: 2px solid blue;
}`,
css`span {
display: block;
border: 3px solid blue;
}`
];
}

render() {
return htmlWithStyles`
<div>Testing1</div>
<span>Testing2</span>`;
}
});
const el = document.createElement(name);
container.appendChild(el);
await (el as LitElement).updateComplete;
assert.equal(el.shadowRoot!.querySelectorAll('style').length, 2);
});

test('static get styles can be a single CSSResult', async () => {
const name = generateElementName();
customElements.define(name, class extends LitElement {
Expand Down

0 comments on commit 2cbe3e0

Please sign in to comment.