Skip to content
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

fix(engine-dom): append global stylesheets to document.head #2923

Merged
merged 5 commits into from
Jul 8, 2022
Merged
Show file tree
Hide file tree
Changes from 2 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
31 changes: 15 additions & 16 deletions packages/@lwc/engine-dom/src/styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ interface CacheData {
// Same as above, but for the global document to avoid an extra WeakMap lookup for this common case.
global: boolean;
// Keep track of whether the <style> element has been used already, so we know if we need to clone it.
// Note that this has no impact on browsers that support constructable stylesheets.
// Note that this has no impact on constructable stylesheets, only <style> elements.
used: boolean;
}

Expand All @@ -66,10 +66,6 @@ if (process.env.NODE_ENV === 'development') {
};
}

function isDocument(target: ShadowRoot | Document): target is Document {
return !isUndefined((target as Document).head);
}

function createFreshStyleElement(content: string) {
const elm = document.createElement('style');
elm.type = 'text/css';
Expand Down Expand Up @@ -121,15 +117,14 @@ function insertConstructableStylesheet(

function insertStyleElement(
content: string,
target: ShadowRoot | Document,
target: ShadowRoot | HTMLHeadElement,
cacheData: StyleElementCacheData
) {
const elm = createStyleElement(content, cacheData);
const targetAnchorPoint = isDocument(target) ? target.head : target;
targetAnchorPoint.appendChild(elm);
target.appendChild(elm);
}

function doInsertStylesheet(content: string, target: ShadowRoot | Document, cacheData: CacheData) {
function doInsertStylesheet(content: string, target: ShadowRoot, cacheData: CacheData) {
// Constructable stylesheets are only supported in certain browsers:
// https://caniuse.com/mdn-api_document_adoptedstylesheets
// The reason we use it is for perf: https://github.com/salesforce/lwc/pull/2460
Expand All @@ -145,13 +140,14 @@ function doInsertStylesheet(content: string, target: ShadowRoot | Document, cach
}
}

function getCacheData(content: string) {
function getCacheData(content: string, forceStyleElement: boolean) {
let cacheData = stylesheetCache.get(content);
if (isUndefined(cacheData)) {
cacheData = {
stylesheet: supportsConstructableStylesheets
? createConstructableStylesheet(content)
: createFreshStyleElement(content),
stylesheet:
supportsConstructableStylesheets && !forceStyleElement
? createConstructableStylesheet(content)
: createFreshStyleElement(content),
roots: undefined,
global: false,
used: false,
Expand All @@ -162,17 +158,20 @@ function getCacheData(content: string) {
}

function insertGlobalStylesheet(content: string) {
const cacheData = getCacheData(content);
// Force a <style> element for global stylesheets. See comment below.
const cacheData = getCacheData(content, true);
if (cacheData.global) {
// already inserted
return;
}
cacheData.global = true; // mark inserted
doInsertStylesheet(content, document, cacheData);

// TODO [#2922]: use document.adoptedStyleSheets in supported browsers. Currently we can't, due to backwards compat.
insertStyleElement(content, document.head, cacheData as StyleElementCacheData);
}

function insertLocalStylesheet(content: string, target: ShadowRoot) {
const cacheData = getCacheData(content);
const cacheData = getCacheData(content, false);
let { roots } = cacheData;
if (isUndefined(roots)) {
roots = cacheData.roots = new WeakSet(); // lazily initialize (not needed for global styles)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { createElement } from 'lwc';
import Component from 'x/component';

// TODO [#2922]: remove this test when we can support document.adoptedStyleSheets.
// Currently we can't, due to backwards compat.
if (!process.env.NATIVE_SHADOW) {
describe('global styles', () => {
it('injects global styles in document.head in synthetic shadow', () => {
const numStyleSheetsBefore = document.styleSheets.length;
const elm = createElement('x-component', { is: Component });
document.body.appendChild(elm);
return Promise.resolve().then(() => {
const numStyleSheetsAfter = document.styleSheets.length;
expect(numStyleSheetsBefore + 1).toEqual(numStyleSheetsAfter);
});
});
});
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
h1 {
color: burlywood;
background: darkslategray;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<template>
<h1>Hello world</h1>
</template>
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { LightningElement } from 'lwc';

export default class extends LightningElement {}