-
Notifications
You must be signed in to change notification settings - Fork 319
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
Native cssstylesheet #853
Native cssstylesheet #853
Conversation
Ping @samthor |
Sorry, I was on paternity leave and then I forgot this when I got back. PTAL. I've changed the code a bit so we don't subclass |
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 breaks recently added getStyles()
API, at least I don't see any call of it anymore. Please fix.
Oops, I didn't notice that change in my rebase. I've restored that line and modified a test to ensure we also call |
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.
Thanks, tested locally and it works for our ThemableElement
, see vaadin/component-mixins#55
@justinfagnani could you please confirm if this change is planned to land in 2.3.0 release?
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 you find a way around adding _nativeStyles
? Seems like there should be a way to have _styles
be a CSSResultOrNative[]
and error only if there's a CSSStyleSheet in there on a platform that doesn't support it.
src/lib/css-tag.ts
Outdated
@@ -9,8 +9,9 @@ part of the polymer project is also subject to an additional IP rights grant | |||
found at http://polymer.github.io/PATENTS.txt | |||
*/ | |||
|
|||
export const supportsAdoptingStyleSheets = | |||
('adoptedStyleSheets' in Document.prototype) && | |||
export const supportsAdoptingShadowStyleSheets = |
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.
Why the name change? This is kind of public API, so I wouldn't...
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.
Sure. I've left the new semantics though, since all we care about is support on a ShadowRoot
. There's a polyfill for IE11 which only supports Document
; in that case, the old behavior was wrong, and would cause a crash.
src/lit-element.ts
Outdated
|
||
private static _styles: CSSResult[]|undefined; | ||
private static _nativeStyles: CSSStyleSheet[]|undefined; |
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.
Why does this need to be separate from _styles
? Doesn't total ordering between the two sets matter too?
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.
We use one or the other depending on browser support. I also though about using a union TypeScript type but it got particularly awkward.
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.
in case it helps, the type signature to merge the two might be like this:
private static _styles: (CSSResult | CSSStyleSheet)[] | undefined
then, when you're looping over each stylesheet, you'd distinguish whether it's a native stylesheet using the instanceof
operator or something along those lines
it might be necessary if for some reason native stylesheets and CSSResult's might both be used simultaneously
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.
Adding _nativeStyles
lets us assign at once to each element—we just set .adoptedStyleSheets = this._nativeStyles
. I think it's much more ergonomic than casting every element of the array when you assign it.
I want to hear what @justinfagnani thinks—mostly I hope I've made it clear that we use either array, so total ordering doesn't matter.
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.
I think it's much more ergonomic than casting every element of the array when you assign it.
i'm not sure i follow.. casting every element when assigning to the array? maybe there's just a bit of confusion about the details of that type signature
the type signature (CSSResult | CSSStyleSheet)[] | undefined
would allow the array to contain stylesheets of either type: so you'd be able to "assign" both types of stylesheets to the array without any type casting
const cssResult: CSSResult = getExampleCssResult()
const nativeCss: CSSStyleSheet = getExampleNativeCss()
this._styles.push(cssResult) // no casting
this._styles.push(nativeCss) // no problem
for (const style of this._styles) {
// style has type: (CSSResult | CSSStyleSheet)
}
however when you read one of the array values, then you might want to cast to distinguish it's type to handle them separately
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.
The type signature should actually be (CSSResult[] | CSSStyleSheet[])
, because you only have CSSStyleSheet
where native adopted stylesheets are supported (regardless of input).
And then the only way you check the type is by doing something like this._styles[0] instanceof CSSStyleSheet
, which is awkward.
src/lit-element.ts
Outdated
@@ -152,30 +172,33 @@ export class LitElement extends UpdatingElement { | |||
} | |||
|
|||
/** | |||
* Applies styling to the element shadowRoot using the `static get styles` | |||
* property. Styling will apply using `shadowRoot.adoptedStyleSheets` where | |||
* Applies styling to the element shadowRoot using the private styles |
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.
I don't think we should mention a private field in a protected API doc
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.
I've reverted this comment. I think it's better the way it was.
My confusion came from... I think the tense is a bit ambiguous. By the time this function is called, we've already created the private "mapping" of styles (via _getUniqueStyles()
), and this function doesn't call the static get styles
method itself. Not a big deal, because we've already called it, but that's why I was eager to modify the comment.
src/lit-element.ts
Outdated
work.push(userStyles); | ||
} | ||
|
||
if (supportsAdoptingShadowStyleSheets) { |
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 do one loop with this check inside? I think it'll be more compact.
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.
We're creating two different arrays. I could change the _styles
and _nativeStyles
to be a type union but I think it'll be more confusing when we apply them in adoptStyles
.
ping @justinfagnani I've rebased the PR again. |
ugh, sorry for noise—I merged badly. I've just made the changes against master again. |
@samthor I tweaked this change to only use one array for both CSSSyleSheets and CSSResults. It's only a small conditional in |
@justinfagnani I pulled your change in and fixed some comments. PTAL |
I've addressed feedback and pushed again. I presume the PR will pass Travis :) |
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 looks ok, but I'm a little concerned about lack of polyfill support. This is masked here because the test is only running if shadowRoot
has adoptedStylesheets
and the polyfill does not.
Let's look into either:
- failing in some more obvious way if the polyfill is on (note, it can be forced on) and a CSSStyleSheet is provided (like just a clear console error or something) or
- trying to pass the cssText from the provided stylesheet to ShadyCSS (presumably this would only work for a subset of stylesheets) and fail with a clear error otherwise.
To be clear, you want to test the case where the platform has native constructible stylesheet support, but the polyfill is also forced on. Otherwise there's no way yet to get a constructible stylesheet. |
I think what y'all mean is, you're worried about the case where there is native constructible stylesheets support but the WC polyfills are forced on. This can only happen in Chromium right now, since that's the only place native constructible stylesheets are supported. Does that sound right? If the target doesn't have constructible stylesheets at all (or that is polyfilled—although that space is a bit fuzzy, we did it for Santa Tracker), I don't think there's an issue there. |
Co-Authored-By: Steve Orvell <[email protected]>
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.
Just the little tweak to the "supports" flag and making sure we understand that the tests are all passing and I think we're g2g.
@@ -12,7 +12,8 @@ found at http://polymer.github.io/PATENTS.txt | |||
/** | |||
* Whether the current browser supports `adoptedStyleSheets`. | |||
*/ | |||
export const supportsAdoptingStyleSheets = | |||
export const supportsAdoptingStyleSheets = (window.ShadowRoot) && |
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.
Think we need to change this to ('adoptedStyleSheets' in window.ShadowRoot.prototype)
, instead of ('adoptedStyleSheets' in Document.prototype)
. This makes sure it'll be false when ShadyDOM is enabled.
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.
Seems like this change should be needed to get the test running under the polyfill to run?
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.
@justinfagnani had an issue with this. To quote him:
We need to keep this checks against Document, since we have developers that delete the properties on Document.prototype to disable the use of adopted style sheets so they can edit in DevTools.
@sorvell @justinfagnani We're good for another review now.
And I've updated the tests a bit. We now explicitly check that, in the fully natively supported case, changing the rules of a |
Co-Authored-By: Steve Orvell <[email protected]>
src/test/lit-element_styling_test.ts
Outdated
// adoptedStyleSheets, we can return a CSSStyleSheet that will be flattened | ||
// and play nice with others. | ||
const testShadyCSSWithAdoptedStyleSheetSupport = (typeof ShadowRoot === 'function') && | ||
('adoptedStyleSheets' in window.ShadowRoot.prototype) && |
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.
I don't think this test ever runs. When using the Shadow DOM polyfill, ShadowRoot
does not have an adoptedStyleSheets
property. Just taking out that check should make this run.
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.
Well, that makes the test fail, because I can't construct CSSStyleSheet
without adoptedStyleSheets
support.
I've changed the logic a bit:
const testShadyCSSWithAdoptedStyleSheetSupport =
(window.ShadowRoot) &&
('replace' in CSSStyleSheet.prototype) &&
(window.ShadyCSS !== undefined && !window.ShadyCSS.nativeShadow);
This uses ShadyCSS
the same way we do in css-tag.ts, and basically says whether we're flattening the stylesheets because the polyfill is included.
Thanks @sorvell for pointing out the test wasn't running. Fixed now. |
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. Thanks for seeing it through!
Thanks for the thorough review. I look forward to the next release so I can pin Santa against it. |
Fixes #774. Supports native
CSSStyleSheet
if and only if native adopted style sheets on shadow roots are supported.