Skip to content

Commit

Permalink
jsx(): Treat __self and __source as normal props (#28257)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
acdlite authored Feb 7, 2024
1 parent f07ac1e commit 91caa96
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 10 deletions.
16 changes: 14 additions & 2 deletions packages/react/src/ReactElementProd.js
Original file line number Diff line number Diff line change
Expand Up @@ -232,8 +232,14 @@ export function createElement(type, config, children) {
hasOwnProperty.call(config, propName) &&
// Skip over reserved prop names
propName !== 'key' &&
// TODO: These will no longer be reserved in the next major
// TODO: `ref` will no longer be reserved in the next major
propName !== 'ref' &&
// ...and maybe these, too, though we currently rely on them for
// warnings and debug information in dev. Need to decide if we're OK
// with dropping them. In the jsx() runtime it's not an issue because
// the data gets passed as separate arguments instead of props, but
// it would be nice to stop relying on them entirely so we can drop
// them from the internal Fiber field.
propName !== '__self' &&
propName !== '__source'
) {
Expand Down Expand Up @@ -375,8 +381,14 @@ export function cloneElement(element, config, children) {
hasOwnProperty.call(config, propName) &&
// Skip over reserved prop names
propName !== 'key' &&
// TODO: These will no longer be reserved in the next major
// TODO: `ref` will no longer be reserved in the next major
propName !== 'ref' &&
// ...and maybe these, too, though we currently rely on them for
// warnings and debug information in dev. Need to decide if we're OK
// with dropping them. In the jsx() runtime it's not an issue because
// the data gets passed as separate arguments instead of props, but
// it would be nice to stop relying on them entirely so we can drop
// them from the internal Fiber field.
propName !== '__self' &&
propName !== '__source'
) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -569,4 +569,26 @@ describe('ReactElementValidator', () => {
React.createElement(Lazy);
expect(didCall).toBe(false);
});

it('__self and __source are treated as normal props', async () => {
// 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.
function Child({__self, __source}) {
return __self + __source;
}

const container = document.createElement('div');
const root = ReactDOMClient.createRoot(container);
// NOTE: The Babel transform treats the presence of these props as a syntax
// error but theoretically it doesn't have to. Using spread here to
// circumvent the syntax error and demonstrate that the runtime
// doesn't care.
const props = {
__self: 'Hello ',
__source: 'world!',
};
await act(() => root.render(<Child {...props} />));
expect(container.textContent).toBe('Hello world!');
});
});
12 changes: 4 additions & 8 deletions packages/react/src/jsx/ReactJSXElement.js
Original file line number Diff line number Diff line change
Expand Up @@ -239,10 +239,8 @@ export function jsx(type, config, maybeKey) {
hasOwnProperty.call(config, propName) &&
// Skip over reserved prop names
propName !== 'key' &&
// TODO: These will no longer be reserved in the next major
propName !== 'ref' &&
propName !== '__self' &&
propName !== '__source'
// TODO: `ref` will no longer be reserved in the next major
propName !== 'ref'
) {
props[propName] = config[propName];
}
Expand Down Expand Up @@ -316,10 +314,8 @@ export function jsxDEV(type, config, maybeKey, source, self) {
hasOwnProperty.call(config, propName) &&
// Skip over reserved prop names
propName !== 'key' &&
// TODO: These will no longer be reserved in the next major
propName !== 'ref' &&
propName !== '__self' &&
propName !== '__source'
// TODO: `ref` will no longer be reserved in the next major
propName !== 'ref'
) {
props[propName] = config[propName];
}
Expand Down

0 comments on commit 91caa96

Please sign in to comment.