fix: Add check for builtin custom elements in `set_custom_element_data` (#16592)

Fixes #16591

This PR introduces a check for builtin custom elements (is attribute) inside the set_custom_element_data helper in order to correctly set properties that have a setter.
pull/16672/head
Edoardo Cavazza 2 weeks ago committed by GitHub
parent 7105736828
commit 6534aa08e3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1,5 @@
---
"svelte": patch
---
fix: Add check for builtin custom elements in `set_custom_element_data`

@ -238,10 +238,10 @@ export function set_custom_element_data(node, prop, value) {
// Don't compute setters for custom elements while they aren't registered yet,
// because during their upgrade/instantiation they might add more setters.
// Instead, fall back to a simple "an object, then set as property" heuristic.
(setters_cache.has(node.nodeName) ||
(setters_cache.has(node.getAttribute('is') || node.nodeName) ||
// customElements may not be available in browser extension contexts
!customElements ||
customElements.get(node.tagName.toLowerCase())
customElements.get(node.getAttribute('is') || node.tagName.toLowerCase())
? get_setters(node).includes(prop)
: value && typeof value === 'object')
) {
@ -546,9 +546,10 @@ var setters_cache = new Map();
/** @param {Element} element */
function get_setters(element) {
var setters = setters_cache.get(element.nodeName);
var cache_key = element.getAttribute('is') || element.nodeName;
var setters = setters_cache.get(cache_key);
if (setters) return setters;
setters_cache.set(element.nodeName, (setters = []));
setters_cache.set(cache_key, (setters = []));
var descriptors;
var proto = element; // In the case of custom elements there might be setters on the instance

@ -20,5 +20,8 @@ export default test({
const [value1, value2] = target.querySelectorAll('value-element');
assert.equal(value1.shadowRoot?.innerHTML, '<span>test</span>');
assert.equal(value2.shadowRoot?.innerHTML, '<span>test</span>');
const value_builtin = target.querySelector('div');
assert.equal(value_builtin?.shadowRoot?.innerHTML, '<span>test</span>');
}
});

@ -15,6 +15,24 @@
}
});
}
if(!customElements.get('value-builtin')) {
customElements.define('value-builtin', class extends HTMLDivElement {
constructor() {
super();
this.attachShadow({ mode: 'open' });
}
set value(v) {
if (this.__value !== v) {
this.__value = v;
this.shadowRoot.innerHTML = `<span>${v}</span>`;
}
}
}, {
extends: 'div'
});
}
</script>
<my-element string="test" object={{ test: true }}></my-element>
@ -22,3 +40,4 @@
<value-element value="test"></value-element>
<value-element {...{value: "test"}}></value-element>
<div is="value-builtin" value="test"></div>

Loading…
Cancel
Save