@lwc/ssr-runtime 8.15.1 → 8.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs.js CHANGED
@@ -625,7 +625,7 @@ function normalizeTabIndex(value) {
625
625
  const shouldNormalize = value > 0 && typeof value !== 'boolean';
626
626
  return shouldNormalize ? 0 : value;
627
627
  }
628
- /** version: 8.15.1 */
628
+ /** version: 8.16.0 */
629
629
 
630
630
  /*
631
631
  * Copyright (c) 2024, Salesforce, Inc.
@@ -1564,7 +1564,15 @@ function fallbackTmplNoYield(emit, shadowSlottedContent, _lightSlottedContent, _
1564
1564
  }
1565
1565
  }
1566
1566
  }
1567
- async function serverSideRenderComponent(tagName, Component, props = {}, mode = DEFAULT_SSR_MODE) {
1567
+ class RenderContext {
1568
+ constructor(styleDedupePrefix, styleDedupeIsEnabled) {
1569
+ this.stylesheetToId = new WeakMap();
1570
+ this.nextId = 0;
1571
+ this.styleDedupeIsEnabled = styleDedupeIsEnabled;
1572
+ this.styleDedupePrefix = styleDedupePrefix;
1573
+ }
1574
+ }
1575
+ async function serverSideRenderComponent(tagName, Component, props = {}, styleDedupePrefix = '', styleDedupeIsEnabled = false, mode = DEFAULT_SSR_MODE) {
1568
1576
  if (typeof tagName !== 'string') {
1569
1577
  throw new Error(`tagName must be a string, found: ${tagName}`);
1570
1578
  }
@@ -1573,6 +1581,7 @@ async function serverSideRenderComponent(tagName, Component, props = {}, mode =
1573
1581
  const emit = (segment) => {
1574
1582
  markup += segment;
1575
1583
  };
1584
+ emit.cxt = new RenderContext(styleDedupePrefix, styleDedupeIsEnabled);
1576
1585
  if (!generateMarkup) {
1577
1586
  // If a non-component is accidentally provided, render an empty template
1578
1587
  emit(`<${tagName}>`);
@@ -1700,7 +1709,11 @@ function hasScopedStaticStylesheets(Component) {
1700
1709
  });
1701
1710
  return scoped;
1702
1711
  }
1703
- function renderStylesheets(defaultStylesheets, defaultScopedStylesheets, staticStylesheets, scopeToken, Component, hasScopedTemplateStyles) {
1712
+ function renderStylesheets(
1713
+ // FIXME: the `emit` function does not exist in the SSR's compiler's yield mode. If we
1714
+ // are going to use it to transport the RenderContext down the call stack, we'll need to figure out
1715
+ // how to make htat work in yield mode.
1716
+ emit, defaultStylesheets, defaultScopedStylesheets, staticStylesheets, scopeToken, Component, hasScopedTemplateStyles) {
1704
1717
  const hasAnyScopedStyles = hasScopedTemplateStyles || hasScopedStaticStylesheets(Component);
1705
1718
  const { renderMode } = Component;
1706
1719
  let result = '';
@@ -1709,10 +1722,25 @@ function renderStylesheets(defaultStylesheets, defaultScopedStylesheets, staticS
1709
1722
  const token = scoped ? scopeToken : undefined;
1710
1723
  const useActualHostSelector = !scoped || renderMode !== 'light';
1711
1724
  const useNativeDirPseudoclass = true;
1712
- const styleContents = stylesheet(token, useActualHostSelector, useNativeDirPseudoclass);
1713
- validateStyleTextContents(styleContents);
1714
- // TODO [#2869]: `<style>`s should not have scope token classes
1715
- result += `<style${hasAnyScopedStyles ? ` class="${scopeToken}"` : ''} type="text/css">${styleContents}</style>`;
1725
+ const { styleDedupeIsEnabled, stylesheetToId, styleDedupePrefix } = emit.cxt;
1726
+ if (!styleDedupeIsEnabled) {
1727
+ const styleContents = stylesheet(token, useActualHostSelector, useNativeDirPseudoclass);
1728
+ validateStyleTextContents(styleContents);
1729
+ result += `<style${hasAnyScopedStyles ? ` class="${scopeToken}"` : ''} type="text/css">${styleContents}</style>`;
1730
+ }
1731
+ else if (stylesheetToId.has(stylesheet)) {
1732
+ const styleId = stylesheetToId.get(stylesheet);
1733
+ result += `<lwc-style style-id="lwc-style-${styleDedupePrefix}-${styleId}"></lwc-style>`;
1734
+ }
1735
+ else {
1736
+ const styleId = emit.cxt.nextId++;
1737
+ stylesheetToId.set(stylesheet, styleId.toString());
1738
+ const styleContents = stylesheet(token, useActualHostSelector, useNativeDirPseudoclass);
1739
+ validateStyleTextContents(styleContents);
1740
+ // TODO [#2869]: `<style>`s should not have scope token classes
1741
+ result += `<style${hasAnyScopedStyles ? ` class="${scopeToken}"` : ''} id="lwc-style-${styleDedupePrefix}-${styleId}" type="text/css">${styleContents}</style>`;
1742
+ result += `<lwc-style style-id="lwc-style-${styleDedupePrefix}-${styleId}"></lwc-style>`;
1743
+ }
1716
1744
  };
1717
1745
  traverseStylesheets(defaultStylesheets, renderStylesheet);
1718
1746
  traverseStylesheets(defaultScopedStylesheets, renderStylesheet);
@@ -1861,5 +1889,5 @@ exports.track = track;
1861
1889
  exports.unwrap = unwrap$1;
1862
1890
  exports.validateStyleTextContents = validateStyleTextContents;
1863
1891
  exports.wire = wire;
1864
- /** version: 8.15.1 */
1892
+ /** version: 8.16.0 */
1865
1893
  //# sourceMappingURL=index.cjs.js.map
package/dist/index.js CHANGED
@@ -621,7 +621,7 @@ function normalizeTabIndex(value) {
621
621
  const shouldNormalize = value > 0 && typeof value !== 'boolean';
622
622
  return shouldNormalize ? 0 : value;
623
623
  }
624
- /** version: 8.15.1 */
624
+ /** version: 8.16.0 */
625
625
 
626
626
  /*
627
627
  * Copyright (c) 2024, Salesforce, Inc.
@@ -1560,7 +1560,15 @@ function fallbackTmplNoYield(emit, shadowSlottedContent, _lightSlottedContent, _
1560
1560
  }
1561
1561
  }
1562
1562
  }
1563
- async function serverSideRenderComponent(tagName, Component, props = {}, mode = DEFAULT_SSR_MODE) {
1563
+ class RenderContext {
1564
+ constructor(styleDedupePrefix, styleDedupeIsEnabled) {
1565
+ this.stylesheetToId = new WeakMap();
1566
+ this.nextId = 0;
1567
+ this.styleDedupeIsEnabled = styleDedupeIsEnabled;
1568
+ this.styleDedupePrefix = styleDedupePrefix;
1569
+ }
1570
+ }
1571
+ async function serverSideRenderComponent(tagName, Component, props = {}, styleDedupePrefix = '', styleDedupeIsEnabled = false, mode = DEFAULT_SSR_MODE) {
1564
1572
  if (typeof tagName !== 'string') {
1565
1573
  throw new Error(`tagName must be a string, found: ${tagName}`);
1566
1574
  }
@@ -1569,6 +1577,7 @@ async function serverSideRenderComponent(tagName, Component, props = {}, mode =
1569
1577
  const emit = (segment) => {
1570
1578
  markup += segment;
1571
1579
  };
1580
+ emit.cxt = new RenderContext(styleDedupePrefix, styleDedupeIsEnabled);
1572
1581
  if (!generateMarkup) {
1573
1582
  // If a non-component is accidentally provided, render an empty template
1574
1583
  emit(`<${tagName}>`);
@@ -1696,7 +1705,11 @@ function hasScopedStaticStylesheets(Component) {
1696
1705
  });
1697
1706
  return scoped;
1698
1707
  }
1699
- function renderStylesheets(defaultStylesheets, defaultScopedStylesheets, staticStylesheets, scopeToken, Component, hasScopedTemplateStyles) {
1708
+ function renderStylesheets(
1709
+ // FIXME: the `emit` function does not exist in the SSR's compiler's yield mode. If we
1710
+ // are going to use it to transport the RenderContext down the call stack, we'll need to figure out
1711
+ // how to make htat work in yield mode.
1712
+ emit, defaultStylesheets, defaultScopedStylesheets, staticStylesheets, scopeToken, Component, hasScopedTemplateStyles) {
1700
1713
  const hasAnyScopedStyles = hasScopedTemplateStyles || hasScopedStaticStylesheets(Component);
1701
1714
  const { renderMode } = Component;
1702
1715
  let result = '';
@@ -1705,10 +1718,25 @@ function renderStylesheets(defaultStylesheets, defaultScopedStylesheets, staticS
1705
1718
  const token = scoped ? scopeToken : undefined;
1706
1719
  const useActualHostSelector = !scoped || renderMode !== 'light';
1707
1720
  const useNativeDirPseudoclass = true;
1708
- const styleContents = stylesheet(token, useActualHostSelector, useNativeDirPseudoclass);
1709
- validateStyleTextContents(styleContents);
1710
- // TODO [#2869]: `<style>`s should not have scope token classes
1711
- result += `<style${hasAnyScopedStyles ? ` class="${scopeToken}"` : ''} type="text/css">${styleContents}</style>`;
1721
+ const { styleDedupeIsEnabled, stylesheetToId, styleDedupePrefix } = emit.cxt;
1722
+ if (!styleDedupeIsEnabled) {
1723
+ const styleContents = stylesheet(token, useActualHostSelector, useNativeDirPseudoclass);
1724
+ validateStyleTextContents(styleContents);
1725
+ result += `<style${hasAnyScopedStyles ? ` class="${scopeToken}"` : ''} type="text/css">${styleContents}</style>`;
1726
+ }
1727
+ else if (stylesheetToId.has(stylesheet)) {
1728
+ const styleId = stylesheetToId.get(stylesheet);
1729
+ result += `<lwc-style style-id="lwc-style-${styleDedupePrefix}-${styleId}"></lwc-style>`;
1730
+ }
1731
+ else {
1732
+ const styleId = emit.cxt.nextId++;
1733
+ stylesheetToId.set(stylesheet, styleId.toString());
1734
+ const styleContents = stylesheet(token, useActualHostSelector, useNativeDirPseudoclass);
1735
+ validateStyleTextContents(styleContents);
1736
+ // TODO [#2869]: `<style>`s should not have scope token classes
1737
+ result += `<style${hasAnyScopedStyles ? ` class="${scopeToken}"` : ''} id="lwc-style-${styleDedupePrefix}-${styleId}" type="text/css">${styleContents}</style>`;
1738
+ result += `<lwc-style style-id="lwc-style-${styleDedupePrefix}-${styleId}"></lwc-style>`;
1739
+ }
1712
1740
  };
1713
1741
  traverseStylesheets(defaultStylesheets, renderStylesheet);
1714
1742
  traverseStylesheets(defaultScopedStylesheets, renderStylesheet);
@@ -1811,5 +1839,5 @@ function createContextProvider(adapter) {
1811
1839
  }
1812
1840
 
1813
1841
  export { ClassList, LightningElement, SYMBOL__DEFAULT_TEMPLATE, SYMBOL__GENERATE_MARKUP, SYMBOL__SET_INTERNALS, api, connectContext, createContextProvider, createElement, establishContextfulRelationship, fallbackTmpl, fallbackTmplNoYield, freezeTemplate, getComponentDef, hasScopedStaticStylesheets, hot, htmlEscape, isComponentConstructor, mutationTracker, normalizeClass, normalizeTabIndex, normalizeTextContent, parseFragment, parseSVGFragment, readonly, registerComponent, registerDecorators, registerTemplate, renderAttrs, renderAttrsNoYield, serverSideRenderComponent as renderComponent, renderStylesheets, renderTextContent, renderer, sanitizeAttribute, sanitizeHtmlContent, serverSideRenderComponent, setFeatureFlag, setFeatureFlagForTest, setHooks, swapComponent, swapStyle, swapTemplate, toIteratorDirective, track, unwrap$1 as unwrap, validateStyleTextContents, wire };
1814
- /** version: 8.15.1 */
1842
+ /** version: 8.16.0 */
1815
1843
  //# sourceMappingURL=index.js.map
package/dist/render.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { type Stylesheet } from '@lwc/shared';
1
2
  import { SYMBOL__GENERATE_MARKUP } from './lightning-element';
2
3
  import type { CompilationMode } from '@lwc/shared';
3
4
  import type { LightningElement, LightningElementConstructor } from './lightning-element';
@@ -50,6 +51,13 @@ export declare function fallbackTmplNoYield(emit: Emit, shadowSlottedContent: Sl
50
51
  interface ComponentWithGenerateMarkup extends LightningElementConstructor {
51
52
  [SYMBOL__GENERATE_MARKUP]?: GenerateMarkupVariants;
52
53
  }
53
- export declare function serverSideRenderComponent(tagName: string, Component: ComponentWithGenerateMarkup, props?: Properties, mode?: CompilationMode): Promise<string>;
54
+ export declare class RenderContext {
55
+ styleDedupeIsEnabled: boolean;
56
+ stylesheetToId: WeakMap<Stylesheet, string>;
57
+ styleDedupePrefix: string;
58
+ nextId: number;
59
+ constructor(styleDedupePrefix: string, styleDedupeIsEnabled: boolean);
60
+ }
61
+ export declare function serverSideRenderComponent(tagName: string, Component: ComponentWithGenerateMarkup, props?: Properties, styleDedupePrefix?: string, styleDedupeIsEnabled?: boolean, mode?: CompilationMode): Promise<string>;
54
62
  export {};
55
63
  //# sourceMappingURL=render.d.ts.map
package/dist/styles.d.ts CHANGED
@@ -1,7 +1,11 @@
1
1
  import type { LightningElementConstructor } from './lightning-element';
2
2
  import type { Stylesheets, Stylesheet } from '@lwc/shared';
3
+ import type { RenderContext } from './render';
3
4
  type ForgivingStylesheets = Stylesheets | Stylesheet | undefined | null | Array<Stylesheets | undefined | null>;
5
+ type EmitFn = ((strSegment: string) => void) & {
6
+ cxt: RenderContext;
7
+ };
4
8
  export declare function hasScopedStaticStylesheets(Component: LightningElementConstructor): boolean;
5
- export declare function renderStylesheets(defaultStylesheets: ForgivingStylesheets, defaultScopedStylesheets: ForgivingStylesheets, staticStylesheets: ForgivingStylesheets, scopeToken: string, Component: LightningElementConstructor, hasScopedTemplateStyles: boolean): string;
9
+ export declare function renderStylesheets(emit: EmitFn, defaultStylesheets: ForgivingStylesheets, defaultScopedStylesheets: ForgivingStylesheets, staticStylesheets: ForgivingStylesheets, scopeToken: string, Component: LightningElementConstructor, hasScopedTemplateStyles: boolean): string;
6
10
  export {};
7
11
  //# sourceMappingURL=styles.d.ts.map
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "You can safely modify dependencies, devDependencies, keywords, etc., but other props will be overwritten."
5
5
  ],
6
6
  "name": "@lwc/ssr-runtime",
7
- "version": "8.15.1",
7
+ "version": "8.16.0",
8
8
  "description": "Runtime complement to @lwc/ssr-compiler",
9
9
  "keywords": [
10
10
  "lwc",
@@ -48,8 +48,8 @@
48
48
  }
49
49
  },
50
50
  "devDependencies": {
51
- "@lwc/shared": "8.15.1",
52
- "@lwc/engine-core": "8.15.1",
51
+ "@lwc/shared": "8.16.0",
52
+ "@lwc/engine-core": "8.16.0",
53
53
  "observable-membrane": "2.0.0"
54
54
  }
55
55
  }