Allow functions to be passed to custom element setters (#23042)

This is part of the new custom element features that were implemented
here:
24dd07bd26

When a custom element has a setter for a property and passes the `in`
heuristic, the value passed to the react property should be assigned
directly to the custom element's property, regardless of the type of the
value. However, it was discovered that this isn't working with
functions. This patch makes it work with functions.

Fixes https://github.com/facebook/react/issues/23041
This commit is contained in:
Joey Arhar
2022-01-12 13:12:07 -07:00
committed by GitHub
parent 9a7e6bf0d0
commit a87adefecd
2 changed files with 33 additions and 4 deletions

View File

@@ -504,6 +504,35 @@ describe('DOMPropertyOperations', () => {
expect(customElement.foo).toBe('two');
expect(customElement.getAttribute('foo')).toBe('one');
});
// @gate enableCustomElementPropertySupport
it('custom element properties should accept functions', () => {
const container = document.createElement('div');
document.body.appendChild(container);
ReactDOM.render(<my-custom-element />, container);
const customElement = container.querySelector('my-custom-element');
// Install a setter to activate the `in` heuristic
Object.defineProperty(customElement, 'foo', {
set: function(x) {
this._foo = x;
},
get: function() {
return this._foo;
},
});
function myFunction() {
return 'this is myFunction';
}
ReactDOM.render(<my-custom-element foo={myFunction} />, container);
expect(customElement.foo).toBe(myFunction);
// Also remove and re-add the property for good measure
ReactDOM.render(<my-custom-element />, container);
expect(customElement.foo).toBe(null);
ReactDOM.render(<my-custom-element foo={myFunction} />, container);
expect(customElement.foo).toBe(myFunction);
});
});
describe('deleteValueForProperty', () => {

View File

@@ -184,10 +184,6 @@ export function setValueForProperty(
}
}
if (shouldRemoveAttribute(name, value, propertyInfo, isCustomComponentTag)) {
value = null;
}
if (
enableCustomElementPropertySupport &&
isCustomComponentTag &&
@@ -197,6 +193,10 @@ export function setValueForProperty(
return;
}
if (shouldRemoveAttribute(name, value, propertyInfo, isCustomComponentTag)) {
value = null;
}
// If the prop isn't in the special list, treat it as a simple attribute.
if (isCustomComponentTag || propertyInfo === null) {
if (isAttributeNameSafe(name)) {