@lwc/ssr-runtime 9.4.6-alpha.0 → 9.5.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 CHANGED
@@ -40,9 +40,6 @@ function registerComponent(..._) {
40
40
  function registerDecorators(..._) {
41
41
  throw new Error('registerDecorators cannot be used in SSR context.');
42
42
  }
43
- function registerTemplate(..._) {
44
- throw new Error('registerTemplate cannot be used in SSR context.');
45
- }
46
43
  function sanitizeAttribute(..._) {
47
44
  throw new Error('sanitizeAttribute cannot be used in SSR context.');
48
45
  }
@@ -467,6 +464,7 @@ function isTrustedContext(target) {
467
464
  }
468
465
  return trustedContext.has(target);
469
466
  }
467
+ const KEY__SANITIZE_HTML_CONTENT = '$sanitizeHtmlContent$';
470
468
  // These are HTML standard prop/attribute IDL mappings, but are not predictable based on camel/kebab-case conversion
471
469
  const SPECIAL_PROPERTY_ATTRIBUTE_MAPPING = /*@__PURE__@*/ new Map([
472
470
  ['accessKey', 'accesskey'],
@@ -631,6 +629,16 @@ function setHooks(hooks) {
631
629
  isFalse$1(hooksAreSet, 'Hooks are already overridden, only one definition is allowed.');
632
630
  hooksAreSet = true;
633
631
  sanitizeHtmlContentImpl = hooks.sanitizeHtmlContent;
632
+ // Synthetic shadow and the runtime bundle with separate copies of @lwc/shared,
633
+ // so they can't directly share the sanitize set with `setHooks`.
634
+ // Set once at boot and left non-writable/non-configurable so the reference stays stable app-wide.
635
+ if (isUndefined$1(globalThis[KEY__SANITIZE_HTML_CONTENT])) {
636
+ defineProperty(globalThis, KEY__SANITIZE_HTML_CONTENT, {
637
+ value: sanitizeHtmlContent,
638
+ writable: false,
639
+ configurable: false,
640
+ });
641
+ }
634
642
  }
635
643
 
636
644
  /*
@@ -680,7 +688,7 @@ function normalizeTabIndex(value) {
680
688
  const shouldNormalize = value > 0 && typeof value !== 'boolean';
681
689
  return shouldNormalize ? 0 : value;
682
690
  }
683
- /** version: 9.4.6-alpha.0 */
691
+ /** version: 9.5.0 */
684
692
 
685
693
  /**
686
694
  * Copyright (c) 2026 Salesforce, Inc.
@@ -704,7 +712,7 @@ function normalizeTabIndex(value) {
704
712
  * @param value
705
713
  * @param msg
706
714
  */
707
- /** version: 9.4.6-alpha.0 */
715
+ /** version: 9.5.0 */
708
716
 
709
717
  /*
710
718
  * Copyright (c) 2023, salesforce.com, inc.
@@ -728,7 +736,7 @@ class SignalBaseClass {
728
736
  }
729
737
  }
730
738
  }
731
- /** version: 9.4.6-alpha.0 */
739
+ /** version: 9.5.0 */
732
740
 
733
741
  /**
734
742
  * Copyright (c) 2026 Salesforce, Inc.
@@ -754,7 +762,6 @@ const features = {
754
762
  DISABLE_HOST_ATTACH_SHADOW_GUARD: null,
755
763
  DISABLE_STRICT_VALIDATION: null,
756
764
  DISABLE_DETACHED_REHYDRATION: null,
757
- DISABLE_BRIDGE_ELEMENT_PROPERTY_GUARD: null,
758
765
  // Remove in 270
759
766
  ENABLE_LEGACY_ITEM_POLYFILL: null,
760
767
  // Remove in 270
@@ -763,12 +770,8 @@ const features = {
763
770
  ENABLE_BROKEN_HTML_COLLECTION_NAMED_ITEM: null,
764
771
  // Remove in 270
765
772
  ENABLE_LEGACY_ATTRIBUTE_CHANGED_CALLBACK: null,
766
- // Remove in 270
767
- DISABLE_HYDRATION_CUSTOM_ELEMENT_CHECK: null,
768
773
  DISABLE_SANITIZED_HTML_CONTENT_IDENTITY_CHECK: null,
769
- ENABLE_INTRINSIC_TEMPLATE_INVOCATION: null,
770
- ENABLE_PARSE_FRAGMENT_SANITIZATION: null,
771
- ENABLE_RENDERER_FACTORY_GUARD: null,
774
+ DISABLE_NATIVE_SHADOWROOT_SINK_SANITIZATION: null,
772
775
  };
773
776
  if (!globalThis.lwcRuntimeFlags) {
774
777
  Object.defineProperty(globalThis, 'lwcRuntimeFlags', { value: create(null) });
@@ -829,7 +832,7 @@ function setFeatureFlagForTest(name, value) {
829
832
  setFeatureFlag(name, value);
830
833
  }
831
834
  }
832
- /** version: 9.4.6-alpha.0 */
835
+ /** version: 9.5.0 */
833
836
 
834
837
  /*
835
838
  * Copyright (c) 2024, Salesforce, Inc.
@@ -874,7 +877,7 @@ class ClassList {
874
877
  listOfClasses[idx] = newClassName;
875
878
  }
876
879
  });
877
- this.el.className = listOfClasses.join(' ');
880
+ this.el.className = Array.from(new Set(listOfClasses)).join(' ');
878
881
  return classWasReplaced;
879
882
  }
880
883
  toggle(classNameToToggle, force) {
@@ -2146,6 +2149,30 @@ function* toIteratorDirective(iterable) {
2146
2149
  }
2147
2150
  }
2148
2151
 
2152
+ /*
2153
+ * Copyright (c) 2026, Salesforce, Inc.
2154
+ * All rights reserved.
2155
+ * SPDX-License-Identifier: MIT
2156
+ * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
2157
+ */
2158
+ const registeredTemplates = new WeakSet();
2159
+ /**
2160
+ * Marks a template as having been generated by the compiler
2161
+ * @param tmpl the compiled template function to register
2162
+ * @returns the same template function, for chaining with an assignment
2163
+ * @internal
2164
+ */
2165
+ function registerTemplate(tmpl) {
2166
+ registeredTemplates.add(tmpl);
2167
+ return tmpl;
2168
+ }
2169
+ function isTemplateRegistered(tmpl) {
2170
+ if (tmpl === null || (typeof tmpl !== 'function' && typeof tmpl !== 'object')) {
2171
+ return false;
2172
+ }
2173
+ return registeredTemplates.has(tmpl);
2174
+ }
2175
+
2149
2176
  /** The class property that holds a component's resolved `@api` allowlist. */
2150
2177
  const PUBLIC_PROPERTIES_KEY = '__lwcPublicProperties__';
2151
2178
  /**
@@ -2221,7 +2248,18 @@ function createComponent(Component, publicProps, wireAdapters, tagName, props, a
2221
2248
  // If a render() function is defined on the class or any of its superclasses, then that takes priority.
2222
2249
  // Next, if the class or any of its superclasses has an implicitly-associated template, then that takes
2223
2250
  // second priority (e.g. a foo.html file alongside a foo.js file). Finally, there is a fallback empty template.
2224
- const renderTemplate = instance.render?.() ?? Component[SYMBOL__DEFAULT_TEMPLATE] ?? defaultTmpl;
2251
+ let renderTemplate;
2252
+ if (instance.render) {
2253
+ renderTemplate = instance.render();
2254
+ if (!isTemplateRegistered(renderTemplate)) {
2255
+ throw new TypeError(`Invalid template returned by the render() method on ${tagName}. It must return ` +
2256
+ `an imported template (e.g.: \`import html from "./${Component.name}.html"\`), ` +
2257
+ `instead, it has returned: ${toString(renderTemplate)}.`);
2258
+ }
2259
+ }
2260
+ else {
2261
+ renderTemplate = Component[SYMBOL__DEFAULT_TEMPLATE] ?? defaultTmpl;
2262
+ }
2225
2263
  const hostHasScopedStylesheets = renderTemplate.hasScopedStylesheets || hasScopedStaticStylesheets(Component);
2226
2264
  const hostScopeToken = hostHasScopedStylesheets
2227
2265
  ? renderTemplate.stylesheetScopeToken + '-host'
@@ -2332,5 +2370,5 @@ exports.track = track;
2332
2370
  exports.unwrap = unwrap$1;
2333
2371
  exports.validateStyleTextContents = validateStyleTextContents;
2334
2372
  exports.wire = wire;
2335
- /** version: 9.4.6-alpha.0 */
2373
+ /** version: 9.5.0 */
2336
2374
  //# sourceMappingURL=index.cjs.map
package/dist/index.d.ts CHANGED
@@ -14,4 +14,5 @@ export { createContextProvider, establishContextfulRelationship, connectContext
14
14
  export { readonly } from './get-read-only-proxy';
15
15
  export { setStaticInternals } from './set-static-internals';
16
16
  export { registerPublicProperties } from './register-public-properties';
17
+ export { registerTemplate } from './register-template';
17
18
  //# sourceMappingURL=index.d.ts.map
package/dist/index.js CHANGED
@@ -36,9 +36,6 @@ function registerComponent(..._) {
36
36
  function registerDecorators(..._) {
37
37
  throw new Error('registerDecorators cannot be used in SSR context.');
38
38
  }
39
- function registerTemplate(..._) {
40
- throw new Error('registerTemplate cannot be used in SSR context.');
41
- }
42
39
  function sanitizeAttribute(..._) {
43
40
  throw new Error('sanitizeAttribute cannot be used in SSR context.');
44
41
  }
@@ -463,6 +460,7 @@ function isTrustedContext(target) {
463
460
  }
464
461
  return trustedContext.has(target);
465
462
  }
463
+ const KEY__SANITIZE_HTML_CONTENT = '$sanitizeHtmlContent$';
466
464
  // These are HTML standard prop/attribute IDL mappings, but are not predictable based on camel/kebab-case conversion
467
465
  const SPECIAL_PROPERTY_ATTRIBUTE_MAPPING = /*@__PURE__@*/ new Map([
468
466
  ['accessKey', 'accesskey'],
@@ -627,6 +625,16 @@ function setHooks(hooks) {
627
625
  isFalse$1(hooksAreSet, 'Hooks are already overridden, only one definition is allowed.');
628
626
  hooksAreSet = true;
629
627
  sanitizeHtmlContentImpl = hooks.sanitizeHtmlContent;
628
+ // Synthetic shadow and the runtime bundle with separate copies of @lwc/shared,
629
+ // so they can't directly share the sanitize set with `setHooks`.
630
+ // Set once at boot and left non-writable/non-configurable so the reference stays stable app-wide.
631
+ if (isUndefined$1(globalThis[KEY__SANITIZE_HTML_CONTENT])) {
632
+ defineProperty(globalThis, KEY__SANITIZE_HTML_CONTENT, {
633
+ value: sanitizeHtmlContent,
634
+ writable: false,
635
+ configurable: false,
636
+ });
637
+ }
630
638
  }
631
639
 
632
640
  /*
@@ -676,7 +684,7 @@ function normalizeTabIndex(value) {
676
684
  const shouldNormalize = value > 0 && typeof value !== 'boolean';
677
685
  return shouldNormalize ? 0 : value;
678
686
  }
679
- /** version: 9.4.6-alpha.0 */
687
+ /** version: 9.5.0 */
680
688
 
681
689
  /**
682
690
  * Copyright (c) 2026 Salesforce, Inc.
@@ -700,7 +708,7 @@ function normalizeTabIndex(value) {
700
708
  * @param value
701
709
  * @param msg
702
710
  */
703
- /** version: 9.4.6-alpha.0 */
711
+ /** version: 9.5.0 */
704
712
 
705
713
  /*
706
714
  * Copyright (c) 2023, salesforce.com, inc.
@@ -724,7 +732,7 @@ class SignalBaseClass {
724
732
  }
725
733
  }
726
734
  }
727
- /** version: 9.4.6-alpha.0 */
735
+ /** version: 9.5.0 */
728
736
 
729
737
  /**
730
738
  * Copyright (c) 2026 Salesforce, Inc.
@@ -750,7 +758,6 @@ const features = {
750
758
  DISABLE_HOST_ATTACH_SHADOW_GUARD: null,
751
759
  DISABLE_STRICT_VALIDATION: null,
752
760
  DISABLE_DETACHED_REHYDRATION: null,
753
- DISABLE_BRIDGE_ELEMENT_PROPERTY_GUARD: null,
754
761
  // Remove in 270
755
762
  ENABLE_LEGACY_ITEM_POLYFILL: null,
756
763
  // Remove in 270
@@ -759,12 +766,8 @@ const features = {
759
766
  ENABLE_BROKEN_HTML_COLLECTION_NAMED_ITEM: null,
760
767
  // Remove in 270
761
768
  ENABLE_LEGACY_ATTRIBUTE_CHANGED_CALLBACK: null,
762
- // Remove in 270
763
- DISABLE_HYDRATION_CUSTOM_ELEMENT_CHECK: null,
764
769
  DISABLE_SANITIZED_HTML_CONTENT_IDENTITY_CHECK: null,
765
- ENABLE_INTRINSIC_TEMPLATE_INVOCATION: null,
766
- ENABLE_PARSE_FRAGMENT_SANITIZATION: null,
767
- ENABLE_RENDERER_FACTORY_GUARD: null,
770
+ DISABLE_NATIVE_SHADOWROOT_SINK_SANITIZATION: null,
768
771
  };
769
772
  if (!globalThis.lwcRuntimeFlags) {
770
773
  Object.defineProperty(globalThis, 'lwcRuntimeFlags', { value: create(null) });
@@ -825,7 +828,7 @@ function setFeatureFlagForTest(name, value) {
825
828
  setFeatureFlag(name, value);
826
829
  }
827
830
  }
828
- /** version: 9.4.6-alpha.0 */
831
+ /** version: 9.5.0 */
829
832
 
830
833
  /*
831
834
  * Copyright (c) 2024, Salesforce, Inc.
@@ -870,7 +873,7 @@ class ClassList {
870
873
  listOfClasses[idx] = newClassName;
871
874
  }
872
875
  });
873
- this.el.className = listOfClasses.join(' ');
876
+ this.el.className = Array.from(new Set(listOfClasses)).join(' ');
874
877
  return classWasReplaced;
875
878
  }
876
879
  toggle(classNameToToggle, force) {
@@ -2142,6 +2145,30 @@ function* toIteratorDirective(iterable) {
2142
2145
  }
2143
2146
  }
2144
2147
 
2148
+ /*
2149
+ * Copyright (c) 2026, Salesforce, Inc.
2150
+ * All rights reserved.
2151
+ * SPDX-License-Identifier: MIT
2152
+ * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
2153
+ */
2154
+ const registeredTemplates = new WeakSet();
2155
+ /**
2156
+ * Marks a template as having been generated by the compiler
2157
+ * @param tmpl the compiled template function to register
2158
+ * @returns the same template function, for chaining with an assignment
2159
+ * @internal
2160
+ */
2161
+ function registerTemplate(tmpl) {
2162
+ registeredTemplates.add(tmpl);
2163
+ return tmpl;
2164
+ }
2165
+ function isTemplateRegistered(tmpl) {
2166
+ if (tmpl === null || (typeof tmpl !== 'function' && typeof tmpl !== 'object')) {
2167
+ return false;
2168
+ }
2169
+ return registeredTemplates.has(tmpl);
2170
+ }
2171
+
2145
2172
  /** The class property that holds a component's resolved `@api` allowlist. */
2146
2173
  const PUBLIC_PROPERTIES_KEY = '__lwcPublicProperties__';
2147
2174
  /**
@@ -2217,7 +2244,18 @@ function createComponent(Component, publicProps, wireAdapters, tagName, props, a
2217
2244
  // If a render() function is defined on the class or any of its superclasses, then that takes priority.
2218
2245
  // Next, if the class or any of its superclasses has an implicitly-associated template, then that takes
2219
2246
  // second priority (e.g. a foo.html file alongside a foo.js file). Finally, there is a fallback empty template.
2220
- const renderTemplate = instance.render?.() ?? Component[SYMBOL__DEFAULT_TEMPLATE] ?? defaultTmpl;
2247
+ let renderTemplate;
2248
+ if (instance.render) {
2249
+ renderTemplate = instance.render();
2250
+ if (!isTemplateRegistered(renderTemplate)) {
2251
+ throw new TypeError(`Invalid template returned by the render() method on ${tagName}. It must return ` +
2252
+ `an imported template (e.g.: \`import html from "./${Component.name}.html"\`), ` +
2253
+ `instead, it has returned: ${toString(renderTemplate)}.`);
2254
+ }
2255
+ }
2256
+ else {
2257
+ renderTemplate = Component[SYMBOL__DEFAULT_TEMPLATE] ?? defaultTmpl;
2258
+ }
2221
2259
  const hostHasScopedStylesheets = renderTemplate.hasScopedStylesheets || hasScopedStaticStylesheets(Component);
2222
2260
  const hostScopeToken = hostHasScopedStylesheets
2223
2261
  ? renderTemplate.stylesheetScopeToken + '-host'
@@ -2272,5 +2310,5 @@ function setStaticInternals(Component, defaultTagName, cmpPublicProps, wireAdapt
2272
2310
  }
2273
2311
 
2274
2312
  export { ClassList, LightningElement, SYMBOL__DEFAULT_TEMPLATE, SYMBOL__GENERATE_MARKUP, SYMBOL__SET_INTERNALS, SignalBaseClass, addTrustedContext as __dangerous_do_not_use_addTrustedContext, addSlottedContent, api, connectContext$1 as connectContext, createContextProvider, createElement, establishContextfulRelationship, fallbackTmpl, fallbackTmplNoYield, freezeTemplate, getComponentDef, hasScopedStaticStylesheets, hot, htmlEscape, isComponentConstructor, isTrustedSignal, mutationTracker, normalizeClass, normalizeTabIndex, normalizeTextContent, parseFragment, parseSVGFragment, readonly, registerComponent, registerDecorators, registerPublicProperties, registerTemplate, renderAttrs, renderAttrsNoYield, serverSideRenderComponent as renderComponent, renderStylesheets, renderTextContent, renderer, sanitizeAttribute, sanitizeHtmlContent, serverSideRenderComponent, setContextKeys, setFeatureFlag, setFeatureFlagForTest, setHooks, setStaticInternals, setTrustedContextSet, setTrustedSignalSet, swapComponent, swapStyle, swapTemplate, toIteratorDirective, track, unwrap$1 as unwrap, validateStyleTextContents, wire };
2275
- /** version: 9.4.6-alpha.0 */
2313
+ /** version: 9.5.0 */
2276
2314
  //# sourceMappingURL=index.js.map
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Marks a template as having been generated by the compiler
3
+ * @param tmpl the compiled template function to register
4
+ * @returns the same template function, for chaining with an assignment
5
+ * @internal
6
+ */
7
+ export declare function registerTemplate<T extends object>(tmpl: T): T;
8
+ export declare function isTemplateRegistered(tmpl: unknown): boolean;
9
+ //# sourceMappingURL=register-template.d.ts.map
@@ -1,14 +1,10 @@
1
1
  import { SYMBOL__DEFAULT_TEMPLATE, type LightningElementConstructor } from './lightning-element';
2
2
  import { type PUBLIC_PROPERTIES_KEY } from './register-public-properties';
3
+ import type { Template } from './types';
3
4
  import type { CompilationMode } from '@lwc/shared';
4
5
  import type { LightningElement } from './lightning-element';
5
6
  import type { WireAdapterConstructor } from '@lwc/engine-core';
6
- interface Template {
7
- (...args: never[]): unknown;
8
- hasScopedStylesheets?: boolean;
9
- stylesheetScopeToken?: string;
10
- }
11
- interface ComponentStaticInternals {
7
+ export interface ComponentStaticInternals {
12
8
  [PUBLIC_PROPERTIES_KEY]?: Set<string>;
13
9
  [SYMBOL__DEFAULT_TEMPLATE]: Template;
14
10
  }
package/dist/stubs.d.ts CHANGED
@@ -7,7 +7,6 @@ export declare function parseFragment(..._: unknown[]): never;
7
7
  export declare function parseSVGFragment(..._: unknown[]): never;
8
8
  export declare function registerComponent(..._: unknown[]): never;
9
9
  export declare function registerDecorators(..._: unknown[]): never;
10
- export declare function registerTemplate(..._: unknown[]): never;
11
10
  export declare function sanitizeAttribute(..._: unknown[]): never;
12
11
  export declare function swapComponent(..._: unknown[]): never;
13
12
  export declare function swapStyle(..._: unknown[]): never;
package/dist/types.d.ts CHANGED
@@ -1,3 +1,8 @@
1
1
  export type Attributes = Record<string, string>;
2
2
  export type Properties = Record<string, unknown>;
3
+ export interface Template {
4
+ (...args: never[]): unknown;
5
+ hasScopedStylesheets?: boolean;
6
+ stylesheetScopeToken?: string;
7
+ }
3
8
  //# sourceMappingURL=types.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": "9.4.6-alpha.0",
7
+ "version": "9.5.0",
8
8
  "description": "Runtime complement to @lwc/ssr-compiler",
9
9
  "keywords": [
10
10
  "lwc",
@@ -53,10 +53,10 @@
53
53
  }
54
54
  },
55
55
  "devDependencies": {
56
- "@lwc/shared": "9.4.6-alpha.0",
57
- "@lwc/engine-core": "9.4.6-alpha.0",
58
- "@lwc/features": "9.4.6-alpha.0",
59
- "@lwc/signals": "9.4.6-alpha.0",
56
+ "@lwc/shared": "9.5.0",
57
+ "@lwc/engine-core": "9.5.0",
58
+ "@lwc/features": "9.5.0",
59
+ "@lwc/signals": "9.5.0",
60
60
  "observable-membrane": "2.0.0"
61
61
  }
62
62
  }