Skip to content

Commit

Permalink
refactor external runtime instruction execution
Browse files Browse the repository at this point in the history
  • Loading branch information
gnoff committed Jan 16, 2023
1 parent d19b102 commit 0c2c4a3
Show file tree
Hide file tree
Showing 8 changed files with 81 additions and 60 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import {
clientRenderBoundary,
completeBoundaryWithStyles,
completeContainerWithStyles,
completeBoundary,
completeContainer,
completeSegment,
Expand Down Expand Up @@ -68,40 +69,49 @@ function installFizzInstrObserver(target /*: Node */) {
}

function handleNode(node_ /*: Node */) {
// $FlowFixMe[incompatible-cast]
if (node_.nodeType !== 1 || !(node_ /*: HTMLElement*/).dataset) {
if (
node_.nodeType !== 1 ||
// $FlowFixMe[incompatible-cast]
!(node_ /*: HTMLElement*/).dataset
) {
return;
}
// $FlowFixMe[incompatible-cast]
const node = (node_ /*: HTMLElement*/);
const dataset = node.dataset;
let register = '';
if (dataset['rxi'] != null) {
clientRenderBoundary(
dataset['bid'],
dataset['dgst'],
dataset['msg'],
dataset['stck'],
);
node.remove();
} else if ((register = dataset['rri']) != null) {
// Convert styles here, since its type is Array<Array<string>>
completeBoundaryWithStyles(
register === 'c' ? completeContainer : completeBoundary,
dataset['bid'],
dataset['sid'],
JSON.parse(dataset['sty']),
);

if (dataset.hasOwnProperty('ri')) {
node.remove();
} else if ((register = dataset['rci']) != null) {
if (register === 'c') {
completeContainer(dataset['bid'], dataset['sid']);
} else {
completeBoundary(dataset['bid'], dataset['sid']);
switch (dataset.ri) {
case 'x':
return clientRenderBoundary(
dataset.bid,
dataset.dgst,
dataset.msg,
dataset.stck,
);
case 's':
return completeSegment(dataset.sid, dataset.pid);
case 'b':
return completeBoundary(dataset.bid, dataset.sid);
case 'rb':
return completeBoundaryWithStyles(
dataset.bid,
dataset.sid,
JSON.parse(dataset.sty),
);
case 'c':
return completeContainer(dataset.bid, dataset.sid);
case 'rc':
return completeContainerWithStyles(
dataset.bid,
dataset.sid,
JSON.parse(dataset.sty),
);
default:
throw new Error(
'React encountered a render instruction it did not recognize.',
);
}
node.remove();
} else if (dataset['rsi'] != null) {
completeSegment(dataset['sid'], dataset['pid']);
node.remove();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2499,7 +2499,7 @@ const completeSegmentScript2 = stringToPrecomputedChunk('","');
const completeSegmentScriptEnd = stringToPrecomputedChunk('")</script>');

const completeSegmentData1 = stringToPrecomputedChunk(
'<template data-rsi="" data-sid="',
'<template data-ri="s" data-sid="',
);
const completeSegmentData2 = stringToPrecomputedChunk('" data-pid="');
const completeSegmentDataEnd = dataElementQuotedEnd;
Expand Down Expand Up @@ -2578,16 +2578,16 @@ const bootstrapContainerOpenEnd = stringToPrecomputedChunk('">');
const bootstrapContainerClose = stringToPrecomputedChunk('</template>');

const completeContainerData1 = stringToPrecomputedChunk(
'<template data-rci="c" data-bid="',
'<template data-ri="c" data-bid="',
);
const completeContainerWithStylesData1 = stringToPrecomputedChunk(
'<template data-rri="c" data-bid="',
'<template data-ri="rc" data-bid="',
);
const completeBoundaryData1 = stringToPrecomputedChunk(
'<template data-rci="" data-bid="',
'<template data-ri="b" data-bid="',
);
const completeBoundaryWithStylesData1 = stringToPrecomputedChunk(
'<template data-rri="" data-bid="',
'<template data-ri="rb" data-bid="',
);
const completeBoundaryOrContainerData2 = stringToPrecomputedChunk(
'" data-sid="',
Expand Down Expand Up @@ -2831,7 +2831,7 @@ const clientRenderErrorScriptArgInterstitial = stringToPrecomputedChunk(',');
const clientRenderScriptEnd = stringToPrecomputedChunk(')</script>');

const clientRenderData1 = stringToPrecomputedChunk(
'<template data-rxi="" data-bid="',
'<template data-ri="x" data-bid="',
);
const clientRenderData2 = stringToPrecomputedChunk('" data-dgst="');
const clientRenderData3 = stringToPrecomputedChunk('" data-msg="');
Expand Down Expand Up @@ -2873,7 +2873,7 @@ export function writeClientRenderBoundaryInstruction(
writeChunk(destination, clientRenderScript1Partial);
}
} else {
// <template data-rxi="" data-bid="
// <template data-ri="x" data-bid="
writeChunk(destination, clientRenderData1);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,47 @@

// Instruction set for the Fizz external runtime

import {LOADED, ERRORED} from './ReactDOMFizzInstructionSetShared';

export {
import {
clientRenderBoundary,
completeBoundary,
completeSegment,
LOADED,
ERRORED,
} from './ReactDOMFizzInstructionSetShared';

export {clientRenderBoundary, completeBoundary, completeSegment};

const resourceMap = new Map();

// This function is almost identical to the version used by inline scripts
// (ReactDOMFizzInstructionSetInlineSource), with the exception of how we read
// completeBoundary and resourceMap
export function completeBoundaryWithStyles(
completionFn,
suspenseBoundaryID,
contentID,
styles,
) {
const complete = completeBoundary.bind(
null,
suspenseBoundaryID,
contentID,
null,
);
const clientRender = completeBoundary.bind(
null,
suspenseBoundaryID,
contentID,
'Stylesheet failed to load.',
);
insertStyles(styles).then(complete, clientRender);
}
export function completeContainerWithStyles(
suspenseBoundaryID,
contentID,
styles,
) {
const complete = completeContainer.bind(null, suspenseBoundaryID, contentID);
insertStyles(styles).then(complete, complete);
}

function insertStyles(styles) {
const precedences = new Map();
const thisDocument = document;
let lastResource, node;
Expand Down Expand Up @@ -100,15 +122,7 @@ export function completeBoundaryWithStyles(
}
}

Promise.all(dependencies).then(
completionFn.bind(null, suspenseBoundaryID, contentID, ''),
completionFn.bind(
null,
suspenseBoundaryID,
contentID,
'Stylesheet failed to load',
),
);
return Promise.all(dependencies);
}

export function completeContainer(containerID, contentID) {
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,6 @@ export function completeBoundaryWithStyles(
}

export function completeContainer(containerID, contentID) {
console.log('completeContainer');
const thisDocument = document;
try {
const contentNode = thisDocument.getElementById(contentID);
Expand Down
4 changes: 2 additions & 2 deletions packages/react-dom/src/__tests__/ReactDOMFloat-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2645,7 +2645,7 @@ describe('ReactDOMFloat', () => {

expect(suspenseInstance.data).toEqual('$!');
expect(boundaryTemplateInstance.dataset.dgst).toBe(
'Stylesheet failed to load',
'Stylesheet failed to load.',
);

expect(getMeaningfulChildren(document)).toEqual(
Expand Down Expand Up @@ -2685,7 +2685,7 @@ describe('ReactDOMFloat', () => {
);
expect(errors).toEqual([
'The server could not finish this Suspense boundary, likely due to an error during server rendering. Switched to client rendering.',
'Stylesheet failed to load',
'Stylesheet failed to load.',
]);
});

Expand Down
5 changes: 1 addition & 4 deletions packages/react-dom/src/test-utils/FizzTestUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -114,10 +114,7 @@ async function replaceScriptsAndMove(
node.nodeType === 1 &&
// $FlowFixMe[prop-missing]
node.dataset != null &&
(node.dataset.rxi != null ||
node.dataset.rri != null ||
node.dataset.rci != null ||
node.dataset.rsi != null)
node.dataset.ri != null
) {
// External runtime assumes that instruction data nodes are eventually
// appended to the body
Expand Down
3 changes: 2 additions & 1 deletion scripts/error-codes/codes.json
Original file line number Diff line number Diff line change
Expand Up @@ -451,5 +451,6 @@
"463": "ReactDOMServer.renderToNodeStream(): The Node Stream API is not available in Bun. Use ReactDOMServer.renderToReadableStream() instead.",
"464": "ReactDOMServer.renderToStaticNodeStream(): The Node Stream API is not available in Bun. Use ReactDOMServer.renderToReadableStream() instead.",
"465": "enableFizzExternalRuntime without enableFloat is not supported. This should never appear in production, since it means you are using a misconfigured React bundle.",
"466": "The root container experienced an error before hydration could begin. The root will switch to client rendering.\n Container Error: \"%s\""
"466": "The root container experienced an error before hydration could begin. The root will switch to client rendering.\n Container Error: \"%s\"",
"467": "React encountered a render instruction it did not recognize."
}

0 comments on commit 0c2c4a3

Please sign in to comment.