fix: spreading attributes on option value attribute get's replaced by option's inner text (#9125)

fixes #9107
Apart from the problem with the option the same happens with the textarea.
pull/9121/head
Teo 1 year ago committed by GitHub
parent 228dd4d9d7
commit 93b17c85f7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -0,0 +1,5 @@
---
'svelte': patch
---
fix: recognize option value on spread attribute

@ -1,5 +1,6 @@
import { is_html, is_svg, is_void } from '../../../shared/utils/names.js';
import Node from './shared/Node.js';
import { walk } from 'estree-walker';
import Attribute from './Attribute.js';
import Binding from './Binding.js';
import EventHandler from './EventHandler.js';
@ -430,7 +431,7 @@ export default class Element extends Node {
}
if (this.name === 'textarea') {
if (info.children.length > 0) {
const value_attribute = info.attributes.find((node) => node.name === 'value');
const value_attribute = get_value_attribute(info.attributes);
if (value_attribute) {
component.error(value_attribute, compiler_errors.textarea_duplicate_value);
return;
@ -449,7 +450,7 @@ export default class Element extends Node {
// Special case — treat these the same way:
// <option>{foo}</option>
// <option value={foo}>{foo}</option>
const value_attribute = info.attributes.find((attribute) => attribute.name === 'value');
const value_attribute = get_value_attribute(info.attributes);
if (!value_attribute) {
info.attributes.push({
type: 'Attribute',
@ -1420,3 +1421,30 @@ function within_custom_element(parent) {
}
return false;
}
/**
* @param {any[]} attributes
*/
function get_value_attribute(attributes) {
let node_value;
attributes.forEach((node) => {
if (node.type !== 'Spread' && node.name.toLowerCase() === 'value') {
node_value = node;
}
if (node.type === 'Spread') {
walk(/** @type {any} */ (node.expression), {
enter(/** @type {import('estree').Node} */ node) {
if (node_value) {
this.skip();
}
if (node.type === 'Identifier') {
if (/** @type {import('estree').Identifier} */ (node).name.toLowerCase() === 'value') {
node_value = node;
}
}
}
});
}
});
return node_value;
}

@ -0,0 +1,7 @@
export default {
html: `
<select>
<option value="value" class="option">Label</option>
</select>
`
};

@ -0,0 +1,3 @@
<select>
<option {...{ value: 'value', class: 'option' }}>Label</option>
</select>
Loading…
Cancel
Save