Skip to content

Commit 91caa96

Browse files
authored
jsx(): Treat __self and __source as normal props (#28257)
These used to be reserved props because the classic React.createElement runtime passed this data as props, whereas the jsxDEV() runtime passes them as separate arguments. This brings us incrementally closer to being able to pass the props object directly through to React instead of cloning a subset into a new object. The React.createElement runtime is unaffected.
1 parent f07ac1e commit 91caa96

File tree

3 files changed

+40
-10
lines changed

3 files changed

+40
-10
lines changed

packages/react/src/ReactElementProd.js

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -232,8 +232,14 @@ export function createElement(type, config, children) {
232232
hasOwnProperty.call(config, propName) &&
233233
// Skip over reserved prop names
234234
propName !== 'key' &&
235-
// TODO: These will no longer be reserved in the next major
235+
// TODO: `ref` will no longer be reserved in the next major
236236
propName !== 'ref' &&
237+
// ...and maybe these, too, though we currently rely on them for
238+
// warnings and debug information in dev. Need to decide if we're OK
239+
// with dropping them. In the jsx() runtime it's not an issue because
240+
// the data gets passed as separate arguments instead of props, but
241+
// it would be nice to stop relying on them entirely so we can drop
242+
// them from the internal Fiber field.
237243
propName !== '__self' &&
238244
propName !== '__source'
239245
) {
@@ -375,8 +381,14 @@ export function cloneElement(element, config, children) {
375381
hasOwnProperty.call(config, propName) &&
376382
// Skip over reserved prop names
377383
propName !== 'key' &&
378-
// TODO: These will no longer be reserved in the next major
384+
// TODO: `ref` will no longer be reserved in the next major
379385
propName !== 'ref' &&
386+
// ...and maybe these, too, though we currently rely on them for
387+
// warnings and debug information in dev. Need to decide if we're OK
388+
// with dropping them. In the jsx() runtime it's not an issue because
389+
// the data gets passed as separate arguments instead of props, but
390+
// it would be nice to stop relying on them entirely so we can drop
391+
// them from the internal Fiber field.
380392
propName !== '__self' &&
381393
propName !== '__source'
382394
) {

packages/react/src/__tests__/ReactElementValidator-test.internal.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -569,4 +569,26 @@ describe('ReactElementValidator', () => {
569569
React.createElement(Lazy);
570570
expect(didCall).toBe(false);
571571
});
572+
573+
it('__self and __source are treated as normal props', async () => {
574+
// These used to be reserved props because the classic React.createElement
575+
// runtime passed this data as props, whereas the jsxDEV() runtime passes
576+
// them as separate arguments.
577+
function Child({__self, __source}) {
578+
return __self + __source;
579+
}
580+
581+
const container = document.createElement('div');
582+
const root = ReactDOMClient.createRoot(container);
583+
// NOTE: The Babel transform treats the presence of these props as a syntax
584+
// error but theoretically it doesn't have to. Using spread here to
585+
// circumvent the syntax error and demonstrate that the runtime
586+
// doesn't care.
587+
const props = {
588+
__self: 'Hello ',
589+
__source: 'world!',
590+
};
591+
await act(() => root.render(<Child {...props} />));
592+
expect(container.textContent).toBe('Hello world!');
593+
});
572594
});

packages/react/src/jsx/ReactJSXElement.js

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -239,10 +239,8 @@ export function jsx(type, config, maybeKey) {
239239
hasOwnProperty.call(config, propName) &&
240240
// Skip over reserved prop names
241241
propName !== 'key' &&
242-
// TODO: These will no longer be reserved in the next major
243-
propName !== 'ref' &&
244-
propName !== '__self' &&
245-
propName !== '__source'
242+
// TODO: `ref` will no longer be reserved in the next major
243+
propName !== 'ref'
246244
) {
247245
props[propName] = config[propName];
248246
}
@@ -316,10 +314,8 @@ export function jsxDEV(type, config, maybeKey, source, self) {
316314
hasOwnProperty.call(config, propName) &&
317315
// Skip over reserved prop names
318316
propName !== 'key' &&
319-
// TODO: These will no longer be reserved in the next major
320-
propName !== 'ref' &&
321-
propName !== '__self' &&
322-
propName !== '__source'
317+
// TODO: `ref` will no longer be reserved in the next major
318+
propName !== 'ref'
323319
) {
324320
props[propName] = config[propName];
325321
}

0 commit comments

Comments
 (0)