pull/16017/head
Rich Harris 4 months ago
parent 9cd02ab5f0
commit da5885e046

@ -1,3 +1,4 @@
/** @import { Expression } from 'estree' */
/** @import { Location } from 'locate-character' */ /** @import { Location } from 'locate-character' */
/** @import { AST } from '#compiler' */ /** @import { AST } from '#compiler' */
/** @import { ComponentContext, ComponentServerTransformState } from '../types.js' */ /** @import { ComponentContext, ComponentServerTransformState } from '../types.js' */
@ -127,29 +128,18 @@ export function RegularElement(node, context) {
} }
} }
const is_option_with_implicit_value = if (
node.name === 'option' && node.name === 'option' &&
!node.attributes.some( !node.attributes.some(
(attribute) => (attribute) =>
attribute.type === 'SpreadAttribute' || attribute.type === 'SpreadAttribute' ||
((attribute.type === 'Attribute' || attribute.type === 'BindDirective') && ((attribute.type === 'Attribute' || attribute.type === 'BindDirective') &&
attribute.name === 'value') attribute.name === 'value')
); )
) {
if (body === null && !is_option_with_implicit_value) {
process_children(trimmed, { ...context, state });
} else {
// we need the body if:
// - it's a <textarea> or a contenteditable element...we will add it ad the inner template in case the value of value is falsy
// - it's a valueless <option> element...we will check the body value at runtime to determine the implicit value selection
const inner_state = { ...state, template: [], init: [] }; const inner_state = { ...state, template: [], init: [] };
process_children(trimmed, { ...context, state: inner_state }); process_children(trimmed, { ...context, state: inner_state });
if (is_option_with_implicit_value) {
// in case of a valueless `<option>` element, $$body is a function that accepts the children...internally it
// will run the children to get the value of the body at runtime since it's needed to for the implicit value
// selection
state.template.push( state.template.push(
b.stmt( b.stmt(
b.call( b.call(
@ -159,8 +149,13 @@ export function RegularElement(node, context) {
) )
) )
); );
} else { } else if (body !== null) {
let id = body; // if this is a `<textarea>` value or a contenteditable binding, we only add
// the body if the attribute/binding is falsy
const inner_state = { ...state, template: [], init: [] };
process_children(trimmed, { ...context, state: inner_state });
let id = /** @type {Expression} */ (body);
if (body.type !== 'Identifier') { if (body.type !== 'Identifier') {
id = b.id(state.scope.generate('$$body')); id = b.id(state.scope.generate('$$body'));
@ -175,7 +170,8 @@ export function RegularElement(node, context) {
b.block([...inner_state.init, ...build_template(inner_state.template)]) b.block([...inner_state.init, ...build_template(inner_state.template)])
) )
); );
} } else {
process_children(trimmed, { ...context, state });
} }
if (select_with_value) { if (select_with_value) {

Loading…
Cancel
Save