Skip to content

Commit

Permalink
toString children of title (#25838)
Browse files Browse the repository at this point in the history
children of title can either behave like children or like an attribute.
We're kind of treating it more like an attribute now so we should
support toString/valueOf like we do on attributes.
  • Loading branch information
sebmarkbage committed Dec 7, 2022
1 parent d4bc16a commit bfcbf33
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 22 deletions.
22 changes: 16 additions & 6 deletions packages/react-dom-bindings/src/client/ReactDOMFloatClient.js
Original file line number Diff line number Diff line change
Expand Up @@ -587,17 +587,27 @@ export function getResource(
return null;
}
case 'title': {
let child = pendingProps.children;
if (Array.isArray(child) && child.length === 1) {
child = child[0];
const children = pendingProps.children;
let child;
if (Array.isArray(children)) {
child = children.length === 1 ? children[0] : null;
} else {
child = children;
}
if (typeof child === 'string' || typeof child === 'number') {
if (
typeof child !== 'function' &&
typeof child !== 'symbol' &&
child !== null &&
child !== undefined
) {
// eslint-disable-next-line react-internal/safe-string-coercion
const childString = '' + (child: any);
const headRoot: Document = getDocumentFromRoot(resourceRoot);
const headResources = getResourcesFromRoot(headRoot).head;
const key = getTitleKey(child);
const key = getTitleKey(childString);
let resource = headResources.get(key);
if (!resource) {
const titleProps = titlePropsFromRawProps(child, pendingProps);
const titleProps = titlePropsFromRawProps(childString, pendingProps);
resource = {
type: 'title',
props: titleProps,
Expand Down
22 changes: 16 additions & 6 deletions packages/react-dom-bindings/src/server/ReactDOMFloatServer.js
Original file line number Diff line number Diff line change
Expand Up @@ -652,17 +652,27 @@ export function resourcesFromElement(type: string, props: Props): boolean {
const resources = currentResources;
switch (type) {
case 'title': {
let child = props.children;
if (Array.isArray(child) && child.length === 1) {
child = child[0];
const children = props.children;
let child;
if (Array.isArray(children)) {
child = children.length === 1 ? children[0] : null;
} else {
child = children;
}
if (typeof child === 'string' || typeof child === 'number') {
const key = 'title::' + child;
if (
typeof child !== 'function' &&
typeof child !== 'symbol' &&
child !== null &&
child !== undefined
) {
// eslint-disable-next-line react-internal/safe-string-coercion
const childString = '' + (child: any);
const key = 'title::' + childString;
let resource = resources.headsMap.get(key);
if (!resource) {
resource = {
type: 'title',
props: titlePropsFromRawProps(child, props),
props: titlePropsFromRawProps(childString, props),
flushed: false,
};
resources.headsMap.set(key, resource);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1473,12 +1473,19 @@ function pushTitleImpl(
}
target.push(endOfStartTag);

const child =
Array.isArray(children) && children.length < 2
? children[0] || null
: children;
if (typeof child === 'string' || typeof child === 'number') {
target.push(stringToChunk(escapeTextForBrowser(child)));
const child = Array.isArray(children)
? children.length < 2
? children[0]
: null
: children;
if (
typeof child !== 'function' &&
typeof child !== 'symbol' &&
child !== null &&
child !== undefined
) {
// eslint-disable-next-line react-internal/safe-string-coercion
target.push(stringToChunk(escapeTextForBrowser('' + child)));
}
target.push(endTag1, stringToChunk('title'), endTag2);
return null;
Expand Down
12 changes: 8 additions & 4 deletions packages/react-dom/src/__tests__/ReactDOMFizzServer-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -5144,8 +5144,10 @@ describe('ReactDOMFizzServer', () => {
}

if (gate(flags => flags.enableFloat)) {
// invalid titles are not emitted on the server when float is on
expect(getVisibleChildren(container)).toEqual(undefined);
// object titles are toStringed when float is on
expect(getVisibleChildren(container)).toEqual(
<title>{'[object Object]'}</title>,
);
} else {
expect(getVisibleChildren(container)).toEqual(<title>hello</title>);
}
Expand All @@ -5159,8 +5161,10 @@ describe('ReactDOMFizzServer', () => {
expect(Scheduler).toFlushAndYield([]);
expect(errors).toEqual([]);
if (gate(flags => flags.enableFloat)) {
// invalid titles are not emitted on the server when float is on
expect(getVisibleChildren(container)).toEqual(undefined);
// object titles are toStringed when float is on
expect(getVisibleChildren(container)).toEqual(
<title>{'[object Object]'}</title>,
);
} else {
expect(getVisibleChildren(container)).toEqual(<title>hello</title>);
}
Expand Down

0 comments on commit bfcbf33

Please sign in to comment.