Skip to content

Commit d07f2c0

Browse files
committed
Inline and combine style flattening and de-duplication
1 parent 52dc1fb commit d07f2c0

File tree

1 file changed

+20
-41
lines changed

1 file changed

+20
-41
lines changed

src/lit-element.ts

Lines changed: 20 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -36,30 +36,7 @@ declare global {
3636

3737
export interface CSSResultArray extends Array<CSSResult|CSSResultArray> {}
3838

39-
/**
40-
* Minimal implementation of Array.prototype.flat
41-
* @param arr the array to flatten
42-
* @param result the accumlated result
43-
*/
44-
function arrayFlat(
45-
styles: CSSResultArray, result: CSSResult[] = []): CSSResult[] {
46-
for (let i = 0, length = styles.length; i < length; i++) {
47-
const value = styles[i];
48-
if (Array.isArray(value)) {
49-
arrayFlat(value, result);
50-
} else {
51-
result.push(value);
52-
}
53-
}
54-
return result;
55-
}
56-
57-
/** Deeply flattens styles array. Uses native flat if available. */
58-
const flattenStyles = (styles: CSSResultArray): CSSResult[] =>
59-
styles.flat ? styles.flat(Infinity) : arrayFlat(styles);
60-
6139
export class LitElement extends UpdatingElement {
62-
6340
/**
6441
* Ensure this class is marked as `finalized` as an optimization ensuring
6542
* it will not needlessly try to `finalize`.
@@ -107,26 +84,28 @@ export class LitElement extends UpdatingElement {
10784
// shared styles will generate new stylesheet objects, which is wasteful.
10885
// This should be addressed when a browser ships constructable
10986
// stylesheets.
110-
const userStyles = this.styles;
111-
const styles: CSSResult[] = [];
87+
const userStyles = this.styles!;
11288
if (Array.isArray(userStyles)) {
113-
const flatStyles = flattenStyles(userStyles);
114-
// As a performance optimization to avoid duplicated styling that can
115-
// occur especially when composing via subclassing, de-duplicate styles
116-
// preserving the last item in the list. The last item is kept to
117-
// try to preserve cascade order with the assumption that it's most
118-
// important that last added styles override previous styles.
119-
const styleSet = flatStyles.reduceRight((set, s) => {
120-
set.add(s);
121-
// on IE set.add does not return the set.
122-
return set;
123-
}, new Set<CSSResult>());
124-
// Array.from does not work on Set in IE
125-
styleSet.forEach((v) => styles.unshift(v));
126-
} else if (userStyles) {
127-
styles.push(userStyles);
89+
// De-duplicate styles preserving the _last_ instance in the set.
90+
// This is a performance optimization to avoid duplicated styles that can
91+
// occur especially when composing via subclassing.
92+
// The last item is kept to try to preserve the cascade order with the
93+
// assumption that it's most important that last added styles override
94+
// previous styles.
95+
const addStyles =
96+
(styles: CSSResultArray, set: Set<CSSResult>): Set<CSSResult> =>
97+
styles.reduceRight(
98+
(set: Set<CSSResult>, s) =>
99+
Array.isArray(s) ? addStyles(s, set) : set.add(s),
100+
set);
101+
// Array.from does not work on Set in IE, otherwise return
102+
// Array.from(addStyles(userStyles, new Set<CSSResult>())).reverse()
103+
const set = addStyles(userStyles, new Set<CSSResult>());
104+
const styles: CSSResult[] = [];
105+
set.forEach((v) => styles.unshift(v));
106+
return styles;
128107
}
129-
return styles;
108+
return [userStyles];
130109
}
131110

132111
private _needsShimAdoptedStyleSheets?: boolean;

0 commit comments

Comments
 (0)