豆豆友情提示:这是一个非官方 GitHub 代理镜像,主要用于网络测试或访问加速。请勿在此进行登录、注册或处理任何敏感信息。进行这些操作请务必访问官方网站 github.com。 Raw 内容也通过此代理提供。
Skip to content

Commit 306a01b

Browse files
authored
Add credentialless as a recognized boolean attribute for iframes (#36148)
## Summary The `credentialless` attribute is a boolean HTML attribute for `<iframe>` elements that loads the iframe in a new, ephemeral context without access to the parent's credentials (cookies, client certificates, etc.). This change adds it to all boolean attribute switch/case lists in React DOM so it is properly handled as a boolean (set when true, removed when false) rather than being treated as an unknown string attribute. Per the [Anonymous iframe spec (WICG)](https://wicg.github.io/anonymous-iframe/): > The credentialless attribute enables loading documents hosted by the iframe with a new and ephemeral storage partition. It is a boolean value. The default is false. ``` partial interface HTMLIFrameElement { attribute boolean credentialless; }; ``` Changes: - ReactDOMComponent.js: Added to both `setProp` and `diffHydratedGenericElement` - ReactFizzConfigDOM.js: Added to `pushAttribute` for server-side rendering - ReactDOMUnknownPropertyHook.js: Added to both validation switch/case lists ## Test plan - Added unit test in DOMPropertyOperations-test.js verifying `credentialless={true}` sets the attribute to `''` and `credentialless={false}` removes it - All tests pass in source and www channels (590 tests each) - Flow type checking passes (dom-node renderer) - Prettier and lint pass
1 parent 3ee1fe4 commit 306a01b

File tree

5 files changed

+45
-0
lines changed

5 files changed

+45
-0
lines changed

packages/react-dom-bindings/src/client/ReactDOMComponent.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -756,6 +756,7 @@ function setProp(
756756
case 'async':
757757
case 'autoPlay':
758758
case 'controls':
759+
case 'credentialless':
759760
case 'default':
760761
case 'defer':
761762
case 'disabled':
@@ -2849,6 +2850,7 @@ function diffHydratedGenericElement(
28492850
case 'async':
28502851
case 'autoPlay':
28512852
case 'controls':
2853+
case 'credentialless':
28522854
case 'default':
28532855
case 'defer':
28542856
case 'disabled':

packages/react-dom-bindings/src/server/ReactFizzConfigDOM.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1695,6 +1695,7 @@ function pushAttribute(
16951695
case 'async':
16961696
case 'autoPlay':
16971697
case 'controls':
1698+
case 'credentialless':
16981699
case 'default':
16991700
case 'defer':
17001701
case 'disabled':

packages/react-dom-bindings/src/shared/ReactDOMUnknownPropertyHook.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,7 @@ function validateProperty(tagName, name, value, eventRegistry) {
208208
case 'async':
209209
case 'autoPlay':
210210
case 'controls':
211+
case 'credentialless':
211212
case 'default':
212213
case 'defer':
213214
case 'disabled':
@@ -287,6 +288,7 @@ function validateProperty(tagName, name, value, eventRegistry) {
287288
case 'async':
288289
case 'autoPlay':
289290
case 'controls':
291+
case 'credentialless':
290292
case 'default':
291293
case 'defer':
292294
case 'disabled':

packages/react-dom/src/__tests__/DOMPropertyOperations-test.js

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,34 @@ describe('DOMPropertyOperations', () => {
160160
expect(container.firstChild.hasAttribute('allowFullScreen')).toBe(false);
161161
});
162162

163+
it('should set credentialless boolean attribute on iframes', async () => {
164+
const container = document.createElement('div');
165+
const root = ReactDOMClient.createRoot(container);
166+
await act(() => {
167+
root.render(<iframe credentialless={true} />);
168+
});
169+
expect(container.firstChild.getAttribute('credentialless')).toBe('');
170+
await act(() => {
171+
root.render(<iframe credentialless={false} />);
172+
});
173+
expect(container.firstChild.hasAttribute('credentialless')).toBe(false);
174+
});
175+
176+
it('should set credentialless attribute when passed a string and warn', async () => {
177+
const container = document.createElement('div');
178+
const root = ReactDOMClient.createRoot(container);
179+
await act(() => {
180+
root.render(<iframe credentialless="true" />);
181+
});
182+
assertConsoleErrorDev([
183+
'Received the string `true` for the boolean attribute `credentialless`. ' +
184+
'Although this works, it will not work as expected if you pass the string "false". ' +
185+
'Did you mean credentialless={true}?\n' +
186+
' in iframe (at **)',
187+
]);
188+
expect(container.firstChild.getAttribute('credentialless')).toBe('');
189+
});
190+
163191
it('should remove when setting custom attr to null', async () => {
164192
const container = document.createElement('div');
165193
const root = ReactDOMClient.createRoot(container);

packages/react-dom/src/__tests__/ReactDOMServerIntegrationAttributes-test.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,18 @@ describe('ReactDOMServerIntegration', () => {
187187
});
188188
});
189189

190+
describe('credentialless property', function () {
191+
itRenders('credentialless prop with true value', async render => {
192+
const e = await render(<iframe credentialless={true} />);
193+
expect(e.getAttribute('credentialless')).toBe('');
194+
});
195+
196+
itRenders('credentialless prop with false value', async render => {
197+
const e = await render(<iframe credentialless={false} />);
198+
expect(e.hasAttribute('credentialless')).toBe(false);
199+
});
200+
});
201+
190202
describe('download property (combined boolean/string attribute)', function () {
191203
itRenders('download prop with true value', async render => {
192204
const e = await render(<a download={true} />);

0 commit comments

Comments
 (0)