From e006ac5d3fa15e30c1add9352bb7c4011223f212 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Sun, 27 Jul 2025 10:31:14 -0400 Subject: [PATCH] always inject styles when compiling as a custom element --- .changeset/wise-hairs-pay.md | 5 +++++ .../src/compiler/phases/2-analyze/index.js | 16 +++++++++------- .../3-transform/client/transform-client.js | 5 +++-- .../custom-element-injected-styles/Thing.svelte | 9 +++++++++ .../custom-element-injected-styles/_config.js | 15 +++++++++++++++ .../custom-element-injected-styles/main.svelte | 5 +++++ 6 files changed, 46 insertions(+), 9 deletions(-) create mode 100644 .changeset/wise-hairs-pay.md create mode 100644 packages/svelte/tests/runtime-runes/samples/custom-element-injected-styles/Thing.svelte create mode 100644 packages/svelte/tests/runtime-runes/samples/custom-element-injected-styles/_config.js create mode 100644 packages/svelte/tests/runtime-runes/samples/custom-element-injected-styles/main.svelte diff --git a/.changeset/wise-hairs-pay.md b/.changeset/wise-hairs-pay.md new file mode 100644 index 0000000000..7d96c1daab --- /dev/null +++ b/.changeset/wise-hairs-pay.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: always inject styles when compiling as a custom element diff --git a/packages/svelte/src/compiler/phases/2-analyze/index.js b/packages/svelte/src/compiler/phases/2-analyze/index.js index d407b44556..cd44fd998a 100644 --- a/packages/svelte/src/compiler/phases/2-analyze/index.js +++ b/packages/svelte/src/compiler/phases/2-analyze/index.js @@ -451,6 +451,8 @@ export function analyze_component(root, source, options) { } } + const is_custom_element = !!options.customElementOptions || options.customElement; + // TODO remove all the ?? stuff, we don't need it now that we're validating the config /** @type {ComponentAnalysis} */ const analysis = { @@ -500,13 +502,13 @@ export function analyze_component(root, source, options) { needs_props: false, event_directive_node: null, uses_event_attributes: false, - custom_element: options.customElementOptions ?? options.customElement, - inject_styles: options.css === 'injected' || options.customElement, - accessors: options.customElement - ? true - : (runes ? false : !!options.accessors) || - // because $set method needs accessors - options.compatibility?.componentApi === 4, + custom_element: is_custom_element, + inject_styles: options.css === 'injected' || is_custom_element, + accessors: + is_custom_element || + (runes ? false : !!options.accessors) || + // because $set method needs accessors + options.compatibility?.componentApi === 4, reactive_statements: new Map(), binding_groups: new Map(), slot_names: new Map(), diff --git a/packages/svelte/src/compiler/phases/3-transform/client/transform-client.js b/packages/svelte/src/compiler/phases/3-transform/client/transform-client.js index 124438a9da..a56aca9c5f 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/transform-client.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/transform-client.js @@ -621,8 +621,9 @@ export function client_component(analysis, options) { ); } - if (analysis.custom_element) { - const ce = analysis.custom_element; + const ce = options.customElementOptions ?? options.customElement; + + if (ce) { const ce_props = typeof ce === 'boolean' ? {} : ce.props || {}; /** @type {ESTree.Property[]} */ diff --git a/packages/svelte/tests/runtime-runes/samples/custom-element-injected-styles/Thing.svelte b/packages/svelte/tests/runtime-runes/samples/custom-element-injected-styles/Thing.svelte new file mode 100644 index 0000000000..0a2b139274 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/custom-element-injected-styles/Thing.svelte @@ -0,0 +1,9 @@ + + +

hello

+ + diff --git a/packages/svelte/tests/runtime-runes/samples/custom-element-injected-styles/_config.js b/packages/svelte/tests/runtime-runes/samples/custom-element-injected-styles/_config.js new file mode 100644 index 0000000000..74597504bd --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/custom-element-injected-styles/_config.js @@ -0,0 +1,15 @@ +import { tick } from 'svelte'; +import { test } from '../../test'; + +export default test({ + mode: ['client'], + async test({ assert, target }) { + const thing = /** @type HTMLElement & { object: { test: true }; } */ ( + target.querySelector('my-thing') + ); + + await tick(); + + assert.include(thing.shadowRoot?.innerHTML, 'red'); + } +}); diff --git a/packages/svelte/tests/runtime-runes/samples/custom-element-injected-styles/main.svelte b/packages/svelte/tests/runtime-runes/samples/custom-element-injected-styles/main.svelte new file mode 100644 index 0000000000..ba5b788da9 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/custom-element-injected-styles/main.svelte @@ -0,0 +1,5 @@ + + +