|
| 1 | +/** @import { Expression } from 'estree' */ |
1 | 2 | /** @import { Location } from 'locate-character' */ |
2 | 3 | /** @import { AST } from '#compiler' */ |
3 | 4 | /** @import { ComponentContext, ComponentServerTransformState } from '../types.js' */ |
@@ -127,55 +128,50 @@ export function RegularElement(node, context) { |
127 | 128 | } |
128 | 129 | } |
129 | 130 |
|
130 | | - const is_option_with_implicit_value = |
| 131 | + if ( |
131 | 132 | node.name === 'option' && |
132 | 133 | !node.attributes.some( |
133 | 134 | (attribute) => |
134 | 135 | attribute.type === 'SpreadAttribute' || |
135 | 136 | ((attribute.type === 'Attribute' || attribute.type === 'BindDirective') && |
136 | 137 | attribute.name === 'value') |
137 | | - ); |
138 | | - |
139 | | - if (body === null && !is_option_with_implicit_value) { |
140 | | - process_children(trimmed, { ...context, state }); |
141 | | - } else { |
142 | | - // we need the body if: |
143 | | - |
144 | | - // - it's a <textarea> or a contenteditable element...we will add it ad the inner template in case the value of value is falsy |
145 | | - // - it's a valueless <option> element...we will check the body value at runtime to determine the implicit value selection |
| 138 | + ) |
| 139 | + ) { |
146 | 140 | const inner_state = { ...state, template: [], init: [] }; |
147 | 141 | process_children(trimmed, { ...context, state: inner_state }); |
148 | 142 |
|
149 | | - if (is_option_with_implicit_value) { |
150 | | - // in case of a valueless `<option>` element, $$body is a function that accepts the children...internally it |
151 | | - // will run the children to get the value of the body at runtime since it's needed to for the implicit value |
152 | | - // selection |
153 | | - state.template.push( |
154 | | - b.stmt( |
155 | | - b.call( |
156 | | - '$.valueless_option', |
157 | | - b.id('$$payload'), |
158 | | - b.thunk(b.block([...inner_state.init, ...build_template(inner_state.template)])) |
159 | | - ) |
| 143 | + state.template.push( |
| 144 | + b.stmt( |
| 145 | + b.call( |
| 146 | + '$.valueless_option', |
| 147 | + b.id('$$payload'), |
| 148 | + b.thunk(b.block([...inner_state.init, ...build_template(inner_state.template)])) |
160 | 149 | ) |
161 | | - ); |
162 | | - } else { |
163 | | - let id = body; |
| 150 | + ) |
| 151 | + ); |
| 152 | + } else if (body !== null) { |
| 153 | + // if this is a `<textarea>` value or a contenteditable binding, we only add |
| 154 | + // the body if the attribute/binding is falsy |
| 155 | + const inner_state = { ...state, template: [], init: [] }; |
| 156 | + process_children(trimmed, { ...context, state: inner_state }); |
164 | 157 |
|
165 | | - if (body.type !== 'Identifier') { |
166 | | - id = b.id(state.scope.generate('$$body')); |
167 | | - state.template.push(b.const(id, body)); |
168 | | - } |
| 158 | + let id = /** @type {Expression} */ (body); |
169 | 159 |
|
170 | | - // Use the body expression as the body if it's truthy, otherwise use the inner template |
171 | | - state.template.push( |
172 | | - b.if( |
173 | | - id, |
174 | | - b.block(build_template([id])), |
175 | | - b.block([...inner_state.init, ...build_template(inner_state.template)]) |
176 | | - ) |
177 | | - ); |
| 160 | + if (body.type !== 'Identifier') { |
| 161 | + id = b.id(state.scope.generate('$$body')); |
| 162 | + state.template.push(b.const(id, body)); |
178 | 163 | } |
| 164 | + |
| 165 | + // Use the body expression as the body if it's truthy, otherwise use the inner template |
| 166 | + state.template.push( |
| 167 | + b.if( |
| 168 | + id, |
| 169 | + b.block(build_template([id])), |
| 170 | + b.block([...inner_state.init, ...build_template(inner_state.template)]) |
| 171 | + ) |
| 172 | + ); |
| 173 | + } else { |
| 174 | + process_children(trimmed, { ...context, state }); |
179 | 175 | } |
180 | 176 |
|
181 | 177 | if (select_with_value) { |
|
0 commit comments