From ab04377bdaf5c440b21247fb1a72b1cda42b63e7 Mon Sep 17 00:00:00 2001 From: Steven Orvell Date: Tue, 8 Oct 2019 17:55:38 -0700 Subject: [PATCH] Add basic support for `adoptedStyleSheets` Uses `shadowRoot.adoptedStyleSheets` for element styling when supported (currently Chrome) and only if a css build is used. The build restriction is in place in order to support `@apply` via ShadyCSS. Currently ShadyCSS works only with a style element in the element template. --- lib/mixins/element-mixin.js | 30 +- lib/utils/settings.js | 5 +- test/runner.html | 1 + .../styling-build-adopted-stylesheets.html | 1027 +++++++++++++++++ 4 files changed, 1061 insertions(+), 2 deletions(-) create mode 100644 test/unit/styling-build-adopted-stylesheets.html diff --git a/lib/mixins/element-mixin.js b/lib/mixins/element-mixin.js index 43902b02e3..b9a7c86477 100644 --- a/lib/mixins/element-mixin.js +++ b/lib/mixins/element-mixin.js @@ -11,7 +11,7 @@ */ import '../utils/boot.js'; -import { rootPath, strictTemplatePolicy, allowTemplateFromDomModule, legacyOptimizations, legacyWarnings, syncInitialRender} from '../utils/settings.js'; +import { rootPath, strictTemplatePolicy, allowTemplateFromDomModule, legacyOptimizations, legacyWarnings, syncInitialRender, supportsAdoptingStyleSheets} from '../utils/settings.js'; import { dedupingMixin } from '../utils/mixin.js'; import { stylesFromTemplate, stylesFromModuleImports } from '../utils/style-gather.js'; import { pathFromUrl, resolveCss, resolveUrl } from '../utils/resolve-url.js'; @@ -294,6 +294,29 @@ export const ElementMixin = dedupingMixin(base => { if (window.ShadyCSS) { window.ShadyCSS.prepareTemplate(template, is); } + // Support for `adoptedStylesheets` relies on using native Shadow DOM + // and built CSS. Built CSS is required because runtime transformation of + // `@apply` is not supported. This is because ShadyCSS relies on being able + // to update a `style` element in the element template and this is + // removed when using `adoptedStyleSheets`. + // Note, it would be more efficient to allow style includes to become + // separate stylesheets; however, because of `@apply` these are + // potentially not shareable and sharing the ones that could be shared + // would require some coordination. To keep it simple, all the includes + // and styles are collapsed into a single shareable stylesheet. + if (builtCSS && supportsAdoptingStyleSheets) { + // Remove styles in template and make a shareable stylesheet + const styles = template.content.querySelectorAll('style'); + if (styles) { + let css = ''; + Array.from(styles).forEach(s => { + css += s.textContent; + s.parentNode.removeChild(s); + }); + klass._styleSheet = new CSSStyleSheet(); + klass._styleSheet.replaceSync(css); + } + } } /** @@ -705,6 +728,11 @@ export const ElementMixin = dedupingMixin(base => { if (!n.shadowRoot) { n.attachShadow({mode: 'open', shadyUpgradeFragment: dom}); n.shadowRoot.appendChild(dom); + // When `adoptedStyleSheets` is supported a stylesheet is made + // available on the element constructor. + if (this.constructor._styleSheet) { + n.shadowRoot.adoptedStyleSheets = [this.constructor._styleSheet]; + } } if (syncInitialRender && window.ShadyDOM) { window.ShadyDOM.flushInitial(n.shadowRoot); diff --git a/lib/utils/settings.js b/lib/utils/settings.js index c4c004933d..eb169524c7 100644 --- a/lib/utils/settings.js +++ b/lib/utils/settings.js @@ -10,9 +10,12 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN import './boot.js'; import { pathFromUrl } from './resolve-url.js'; -export const useShadow = !(window.ShadyDOM); +export const useShadow = !(window.ShadyDOM) || !(window.ShadyDOM.inUse); export const useNativeCSSProperties = Boolean(!window.ShadyCSS || window.ShadyCSS.nativeCss); export const useNativeCustomElements = !(window.customElements.polyfillWrapFlushCallback); +export const supportsAdoptingStyleSheets = useShadow && + ('adoptedStyleSheets' in Document.prototype) && + ('replaceSync' in CSSStyleSheet.prototype); /** diff --git a/test/runner.html b/test/runner.html index e87d2e898e..d2b1c2a3b0 100644 --- a/test/runner.html +++ b/test/runner.html @@ -46,6 +46,7 @@ 'unit/styling-cross-scope-apply.html', 'unit/styling-cross-scope-unknown-host.html', 'unit/styling-only-with-template.html', + 'unit/styling-build-adopted-stylesheets.html', 'unit/custom-style.html', 'unit/custom-style-late.html', 'unit/custom-style-async.html', diff --git a/test/unit/styling-build-adopted-stylesheets.html b/test/unit/styling-build-adopted-stylesheets.html new file mode 100644 index 0000000000..b917cfe505 --- /dev/null +++ b/test/unit/styling-build-adopted-stylesheets.html @@ -0,0 +1,1027 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
no margin
+ + +
Foo
+
Bar
+
Content
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +