Skip to content

Commit fb7fe19

Browse files
committed
Pre tags innerHTML needs to be prefixed
This is because if you do the equivalent on the client using innerHTML, this is the effect you'd get.
1 parent c7c8277 commit fb7fe19

File tree

1 file changed

+58
-20
lines changed

1 file changed

+58
-20
lines changed

packages/react-dom/src/server/ReactDOMServerFormatConfig.js

Lines changed: 58 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1101,30 +1101,68 @@ function pushStartPreformattedElement(
11011101
responseState: ResponseState,
11021102
assignID: null | SuspenseBoundaryID,
11031103
): ReactNodeList {
1104-
const children = pushStartGenericElement(
1105-
target,
1106-
props,
1107-
tag,
1108-
responseState,
1109-
assignID,
1110-
);
1104+
target.push(startChunkForTag(tag));
1105+
1106+
let children = null;
1107+
let innerHTML = null;
1108+
for (const propKey in props) {
1109+
if (hasOwnProperty.call(props, propKey)) {
1110+
const propValue = props[propKey];
1111+
if (propValue == null) {
1112+
continue;
1113+
}
1114+
switch (propKey) {
1115+
case 'children':
1116+
children = propValue;
1117+
break;
1118+
case 'dangerouslySetInnerHTML':
1119+
innerHTML = propValue;
1120+
break;
1121+
default:
1122+
pushAttribute(target, responseState, propKey, propValue);
1123+
break;
1124+
}
1125+
}
1126+
}
1127+
if (assignID !== null) {
1128+
pushID(target, responseState, assignID, props.id);
1129+
}
1130+
1131+
target.push(endOfStartTag);
1132+
1133+
// text/html ignores the first character in these tags if it's a newline
1134+
// Prefer to break application/xml over text/html (for now) by adding
1135+
// a newline specifically to get eaten by the parser. (Alternately for
1136+
// textareas, replacing "^\n" with "\r\n" doesn't get eaten, and the first
1137+
// \r is normalized out by HTMLTextAreaElement#value.)
1138+
// See: <http://www.w3.org/TR/html-polyglot/#newlines-in-textarea-and-pre>
1139+
// See: <http://www.w3.org/TR/html5/syntax.html#element-restrictions>
1140+
// See: <http://www.w3.org/TR/html5/syntax.html#newlines>
1141+
// See: Parsing of "textarea" "listing" and "pre" elements
1142+
// from <http://www.w3.org/TR/html5/syntax.html#parsing-main-inbody>
1143+
// TODO: This doesn't deal with the case where the child is an array
1144+
// or component that returns a string.
1145+
if (innerHTML != null) {
1146+
invariant(
1147+
children == null,
1148+
'Can only set one of `children` or `props.dangerouslySetInnerHTML`.',
1149+
);
11111150

1151+
invariant(
1152+
typeof innerHTML === 'object' && '__html' in innerHTML,
1153+
'`props.dangerouslySetInnerHTML` must be in the form `{__html: ...}`. ' +
1154+
'Please visit https://reactjs.org/link/dangerously-set-inner-html ' +
1155+
'for more information.',
1156+
);
1157+
const html = innerHTML.__html;
1158+
if (typeof html === 'string' && html[0] === '\n') {
1159+
target.push(leadingNewline);
1160+
}
1161+
target.push(stringToChunk(html));
1162+
}
11121163
if (typeof children === 'string' && children[0] === '\n') {
1113-
// text/html ignores the first character in these tags if it's a newline
1114-
// Prefer to break application/xml over text/html (for now) by adding
1115-
// a newline specifically to get eaten by the parser. (Alternately for
1116-
// textareas, replacing "^\n" with "\r\n" doesn't get eaten, and the first
1117-
// \r is normalized out by HTMLTextAreaElement#value.)
1118-
// See: <http://www.w3.org/TR/html-polyglot/#newlines-in-textarea-and-pre>
1119-
// See: <http://www.w3.org/TR/html5/syntax.html#element-restrictions>
1120-
// See: <http://www.w3.org/TR/html5/syntax.html#newlines>
1121-
// See: Parsing of "textarea" "listing" and "pre" elements
1122-
// from <http://www.w3.org/TR/html5/syntax.html#parsing-main-inbody>
1123-
// TODO: This doesn't deal with the case where the child is an array
1124-
// or component that returns a string.
11251164
target.push(leadingNewline);
11261165
}
1127-
11281166
return children;
11291167
}
11301168

0 commit comments

Comments
 (0)