Skip to content

Commit 32e628f

Browse files
committed
fix: restore scoped classes on <option>
1 parent 525679a commit 32e628f

File tree

2 files changed

+40
-14
lines changed

2 files changed

+40
-14
lines changed

packages/svelte/src/compiler/phases/3-transform/server/visitors/RegularElement.js

Lines changed: 34 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,7 @@ export function RegularElement(node, context) {
4141

4242
const optimiser = new PromiseOptimiser();
4343

44-
state.template.push(b.literal(`<${node.name}`));
45-
46-
// If this element needs special handling (like <select value>),
44+
// If this element needs special handling (like <select value> / <option>),
4745
// avoid calling build_element_attributes here to prevent evaluating/awaiting
4846
// attribute expressions twice. We'll handle attributes in the special branch.
4947
const is_select_special =
@@ -54,9 +52,13 @@ export function RegularElement(node, context) {
5452
attribute.name === 'value') ||
5553
attribute.type === 'SpreadAttribute'
5654
);
55+
const is_option_special = node.name === 'option';
56+
const is_special = is_select_special || is_option_special;
5757

5858
let body = /** @type {Expression | null} */ (null);
59-
if (!is_select_special) {
59+
if (!is_special) {
60+
// only open the tag in the non-special path
61+
state.template.push(b.literal(`<${node.name}`));
6062
body = build_element_attributes(node, { ...context, state }, optimiser.transform);
6163
state.template.push(b.literal(node_is_void ? '/>' : '>')); // add `/>` for XHTML compliance
6264
}
@@ -170,14 +172,32 @@ export function RegularElement(node, context) {
170172
}
171173

172174
if (node.name === 'option') {
173-
const attributes = build_spread_object(
175+
/** @type {Array<AST.Attribute | AST.SpreadAttribute | AST.BindDirective>} */
176+
const option_attributes = [];
177+
/** @type {AST.ClassDirective[]} */
178+
const class_directives = [];
179+
/** @type {AST.StyleDirective[]} */
180+
const style_directives = [];
181+
182+
for (const attribute of node.attributes) {
183+
if (
184+
attribute.type === 'Attribute' ||
185+
attribute.type === 'BindDirective' ||
186+
attribute.type === 'SpreadAttribute'
187+
) {
188+
option_attributes.push(attribute);
189+
} else if (attribute.type === 'ClassDirective') {
190+
class_directives.push(attribute);
191+
} else if (attribute.type === 'StyleDirective') {
192+
style_directives.push(attribute);
193+
}
194+
}
195+
196+
const { object, css_hash, classes, styles, flags } = prepare_element_spread(
174197
node,
175-
node.attributes.filter(
176-
(attribute) =>
177-
attribute.type === 'Attribute' ||
178-
attribute.type === 'BindDirective' ||
179-
attribute.type === 'SpreadAttribute'
180-
),
198+
option_attributes,
199+
style_directives,
200+
class_directives,
181201
context,
182202
optimiser.transform
183203
);
@@ -199,7 +219,9 @@ export function RegularElement(node, context) {
199219
);
200220
}
201221

202-
const statement = b.stmt(b.call('$$renderer.option', attributes, body));
222+
const statement = b.stmt(
223+
b.call('$$renderer.option', object, body, css_hash, classes, styles, flags)
224+
);
203225

204226
if (optimiser.expressions.length > 0) {
205227
context.state.template.push(

packages/svelte/src/internal/server/renderer.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -180,9 +180,13 @@ export class Renderer {
180180
/**
181181
* @param {Record<string, any>} attrs
182182
* @param {string | number | boolean | ((renderer: Renderer) => void)} body
183+
* @param {string | undefined} [css_hash]
184+
* @param {Record<string, boolean> | undefined} [classes]
185+
* @param {Record<string, string> | undefined} [styles]
186+
* @param {number | undefined} [flags]
183187
*/
184-
option(attrs, body) {
185-
this.#out.push(`<option${attributes(attrs)}`);
188+
option(attrs, body, css_hash, classes, styles, flags) {
189+
this.#out.push(`<option${attributes(attrs, css_hash, classes, styles, flags)}`);
186190

187191
/**
188192
* @param {Renderer} renderer

0 commit comments

Comments
 (0)