Skip to content

Commit 229bb85

Browse files
committed
jsx(): Treat __self and __source as normal props
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 1beb941 commit 229bb85

File tree

3 files changed

+31
-5
lines changed

3 files changed

+31
-5
lines changed

packages/react/src/ReactElementProd.js

Lines changed: 7 additions & 1 deletion
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
) {

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: 2 additions & 4 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
}

0 commit comments

Comments
 (0)