[Fizz] Implement all the DOM attributes and special cases (#21153)

* Implement DOM format config structure

* Styles

* Input warnings

* Textarea special cases

* Select special cases

* Option special cases

We read the currently selected value from the FormatContext.

* Warning for non-lower case HTML

We don't change to lower case at runtime anymore but keep the warning.

* 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.

* Extract errors
This commit is contained in:
Sebastian Markbåge 2021-03-31 20:39:38 -04:00 committed by GitHub
parent 0e96bdd4ee
commit b9e4c10e99
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 1144 additions and 46 deletions

View File

@ -428,7 +428,7 @@ describe('ReactDOMFizzServer', () => {
}
function AsyncCol({className}) {
return <col className={readText(className)}>{[]}</col>;
return <col className={readText(className)} />;
}
function AsyncPath({id}) {

File diff suppressed because it is too large Load Diff

View File

@ -7,6 +7,8 @@
* @flow
*/
import type {ReactNodeList} from 'shared/ReactTypes';
import type {
Destination,
Chunk,
@ -134,14 +136,16 @@ export function pushStartInstance(
type: string,
props: Object,
responseState: ResponseState,
formatContext: FormatContext,
assignID: null | SuspenseBoundaryID,
): void {
): ReactNodeList {
target.push(
INSTANCE,
stringToChunk(type),
END, // Null terminated type string
// TODO: props
);
return props.children;
}
export function pushEndInstance(

View File

@ -14,6 +14,8 @@
* environment.
*/
import type {ReactNodeList} from 'shared/ReactTypes';
import ReactFizzServer from 'react-server';
type Instance = {|
@ -97,7 +99,7 @@ const ReactNoopServer = ReactFizzServer({
target: Array<Uint8Array>,
type: string,
props: Object,
): void {
): ReactNodeList {
const instance: Instance = {
type: type,
children: [],
@ -105,6 +107,7 @@ const ReactNoopServer = ReactFizzServer({
hidden: false,
};
target.push(Buffer.from(JSON.stringify(instance), 'utf8'));
return props.children;
},
pushEndInstance(

View File

@ -302,6 +302,11 @@ function renderNode(request: Request, task: Task, node: ReactNodeList): void {
return;
}
if (node === null) {
pushEmpty(task.blockedSegment.chunks, request.responseState, task.assignID);
return;
}
if (
typeof node !== 'object' ||
!node ||
@ -347,18 +352,19 @@ function renderNode(request: Request, task: Task, node: ReactNodeList): void {
}
} else if (typeof type === 'string') {
const segment = task.blockedSegment;
pushStartInstance(
const children = pushStartInstance(
segment.chunks,
type,
props,
request.responseState,
segment.formatContext,
task.assignID,
);
// We must have assigned it already above so we don't need this anymore.
task.assignID = null;
const prevContext = segment.formatContext;
segment.formatContext = getChildFormatContext(prevContext, type, props);
renderNode(request, task, props.children);
renderNode(request, task, children);
// We expect that errors will fatal the whole task and that we don't need
// the correct context. Therefore this is not in a finally.
segment.formatContext = prevContext;

View File

@ -385,5 +385,8 @@
"394": "startTransition cannot be called during server rendering.",
"395": "An ID must have been assigned before we can complete the boundary.",
"396": "More boundaries or placeholders than we expected to ever emit.",
"397": "Unknown insertion mode. This is a bug in React."
"397": "Unknown insertion mode. This is a bug in React.",
"398": "`dangerouslySetInnerHTML` does not work on <option>.",
"399": "%s is a self-closing tag and must neither have `children` nor use `dangerouslySetInnerHTML`.",
"400": "menuitems cannot have `children` nor `dangerouslySetInnerHTML`."
}