diff --git a/packages/eslint-plugin-react-hooks/CHANGELOG.md b/packages/eslint-plugin-react-hooks/CHANGELOG.md
index fde29f763089..9ae0b7c65462 100644
--- a/packages/eslint-plugin-react-hooks/CHANGELOG.md
+++ b/packages/eslint-plugin-react-hooks/CHANGELOG.md
@@ -8,7 +8,7 @@
This release adds ESLint v10 support, improves performance by skipping compilation for non-React files, and includes compiler lint improvements including better `set-state-in-effect` detection, improved ref validation, and more helpful error reporting.
-- Add ESLint v10 support. ([@nicolo-ribaudo](https://github.com/nicolo-ribaudo) in [#35720](https://github.com/facebook/react/pull/35720))
+- Add ESLint v10 support. ([@azat-io](https://github.com/azat-io) in [#35720](https://github.com/facebook/react/pull/35720))
- Skip compilation for non-React files to improve performance. ([@josephsavona](https://github.com/josephsavona) in [#35589](https://github.com/facebook/react/pull/35589))
- Fix exhaustive deps bug with Flow type casting. ([@jorge-cab](https://github.com/jorge-cab) in [#35691](https://github.com/facebook/react/pull/35691))
- Fix `useEffectEvent` checks in component syntax. ([@jbrown215](https://github.com/jbrown215) in [#35041](https://github.com/facebook/react/pull/35041))
diff --git a/packages/react-dom-bindings/src/client/ReactDOMComponent.js b/packages/react-dom-bindings/src/client/ReactDOMComponent.js
index 1b25e3727023..80ee96a87a8f 100644
--- a/packages/react-dom-bindings/src/client/ReactDOMComponent.js
+++ b/packages/react-dom-bindings/src/client/ReactDOMComponent.js
@@ -756,6 +756,7 @@ function setProp(
case 'async':
case 'autoPlay':
case 'controls':
+ case 'credentialless':
case 'default':
case 'defer':
case 'disabled':
@@ -2849,6 +2850,7 @@ function diffHydratedGenericElement(
case 'async':
case 'autoPlay':
case 'controls':
+ case 'credentialless':
case 'default':
case 'defer':
case 'disabled':
diff --git a/packages/react-dom-bindings/src/server/ReactFizzConfigDOM.js b/packages/react-dom-bindings/src/server/ReactFizzConfigDOM.js
index 73ce8d3dd29f..691e49e563fd 100644
--- a/packages/react-dom-bindings/src/server/ReactFizzConfigDOM.js
+++ b/packages/react-dom-bindings/src/server/ReactFizzConfigDOM.js
@@ -1695,6 +1695,7 @@ function pushAttribute(
case 'async':
case 'autoPlay':
case 'controls':
+ case 'credentialless':
case 'default':
case 'defer':
case 'disabled':
diff --git a/packages/react-dom-bindings/src/shared/ReactDOMUnknownPropertyHook.js b/packages/react-dom-bindings/src/shared/ReactDOMUnknownPropertyHook.js
index f45e477d876f..aee7d9adb7df 100644
--- a/packages/react-dom-bindings/src/shared/ReactDOMUnknownPropertyHook.js
+++ b/packages/react-dom-bindings/src/shared/ReactDOMUnknownPropertyHook.js
@@ -208,6 +208,7 @@ function validateProperty(tagName, name, value, eventRegistry) {
case 'async':
case 'autoPlay':
case 'controls':
+ case 'credentialless':
case 'default':
case 'defer':
case 'disabled':
@@ -287,6 +288,7 @@ function validateProperty(tagName, name, value, eventRegistry) {
case 'async':
case 'autoPlay':
case 'controls':
+ case 'credentialless':
case 'default':
case 'defer':
case 'disabled':
diff --git a/packages/react-dom/src/__tests__/DOMPropertyOperations-test.js b/packages/react-dom/src/__tests__/DOMPropertyOperations-test.js
index ef09e49bf36c..5bbc2c8dbac8 100644
--- a/packages/react-dom/src/__tests__/DOMPropertyOperations-test.js
+++ b/packages/react-dom/src/__tests__/DOMPropertyOperations-test.js
@@ -160,6 +160,34 @@ describe('DOMPropertyOperations', () => {
expect(container.firstChild.hasAttribute('allowFullScreen')).toBe(false);
});
+ it('should set credentialless boolean attribute on iframes', async () => {
+ const container = document.createElement('div');
+ const root = ReactDOMClient.createRoot(container);
+ await act(() => {
+ root.render();
+ });
+ expect(container.firstChild.getAttribute('credentialless')).toBe('');
+ await act(() => {
+ root.render();
+ });
+ expect(container.firstChild.hasAttribute('credentialless')).toBe(false);
+ });
+
+ it('should set credentialless attribute when passed a string and warn', async () => {
+ const container = document.createElement('div');
+ const root = ReactDOMClient.createRoot(container);
+ await act(() => {
+ root.render();
+ });
+ assertConsoleErrorDev([
+ 'Received the string `true` for the boolean attribute `credentialless`. ' +
+ 'Although this works, it will not work as expected if you pass the string "false". ' +
+ 'Did you mean credentialless={true}?\n' +
+ ' in iframe (at **)',
+ ]);
+ expect(container.firstChild.getAttribute('credentialless')).toBe('');
+ });
+
it('should remove when setting custom attr to null', async () => {
const container = document.createElement('div');
const root = ReactDOMClient.createRoot(container);
diff --git a/packages/react-dom/src/__tests__/ReactDOMServerIntegrationAttributes-test.js b/packages/react-dom/src/__tests__/ReactDOMServerIntegrationAttributes-test.js
index be5ff44b8cd1..9857718c35b7 100644
--- a/packages/react-dom/src/__tests__/ReactDOMServerIntegrationAttributes-test.js
+++ b/packages/react-dom/src/__tests__/ReactDOMServerIntegrationAttributes-test.js
@@ -187,6 +187,18 @@ describe('ReactDOMServerIntegration', () => {
});
});
+ describe('credentialless property', function () {
+ itRenders('credentialless prop with true value', async render => {
+ const e = await render();
+ expect(e.getAttribute('credentialless')).toBe('');
+ });
+
+ itRenders('credentialless prop with false value', async render => {
+ const e = await render();
+ expect(e.hasAttribute('credentialless')).toBe(false);
+ });
+ });
+
describe('download property (combined boolean/string attribute)', function () {
itRenders('download prop with true value', async render => {
const e = await render();