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.
This commit is contained in:
Andrew Clark
2024-02-06 20:03:02 -05:00
committed by GitHub
parent f07ac1e268
commit 91caa96e42
3 changed files with 40 additions and 10 deletions
+14 -2
View File
@@ -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'
) {
@@ -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'
) {
@@ -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!');
});
});
+4 -8
View File
@@ -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];
}
@@ -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];
}