diff --git a/packages/react-dom-bindings/src/server/ReactDOMLegacyServerStreamConfig.js b/packages/react-dom-bindings/src/server/ReactDOMLegacyServerStreamConfig.js index 9b4020e998c5e..1988170779e4c 100644 --- a/packages/react-dom-bindings/src/server/ReactDOMLegacyServerStreamConfig.js +++ b/packages/react-dom-bindings/src/server/ReactDOMLegacyServerStreamConfig.js @@ -12,8 +12,8 @@ export interface Destination { destroy(error: Error): mixed; } -export type PrecomputedChunk = string; -export type Chunk = string; +export opaque type PrecomputedChunk = string; +export opaque type Chunk = string; export function scheduleWork(callback: () => void) { callback(); diff --git a/packages/react-dom-bindings/src/server/ReactDOMServerFormatConfig.js b/packages/react-dom-bindings/src/server/ReactDOMServerFormatConfig.js index c62945a02520a..ba6940fdfd7a4 100644 --- a/packages/react-dom-bindings/src/server/ReactDOMServerFormatConfig.js +++ b/packages/react-dom-bindings/src/server/ReactDOMServerFormatConfig.js @@ -2385,7 +2385,7 @@ export function writeInitialResources( } else { target.push( precedencePlaceholderStart, - escapeTextForBrowser(stringToChunk(precedence)), + stringToChunk(escapeTextForBrowser(precedence)), precedencePlaceholderEnd, ); } @@ -2417,7 +2417,7 @@ export function writeInitialResources( case 'title': { pushStartTitleImpl(target, r.props, responseState); if (typeof r.props.children === 'string') { - target.push(escapeTextForBrowser(stringToChunk(r.props.children))); + target.push(stringToChunk(escapeTextForBrowser(r.props.children))); } pushEndInstance(target, target, 'title', r.props); break; @@ -2518,7 +2518,7 @@ export function writeImmediateResources( case 'title': { pushStartTitleImpl(target, r.props, responseState); if (typeof r.props.children === 'string') { - target.push(escapeTextForBrowser(stringToChunk(r.props.children))); + target.push(stringToChunk(escapeTextForBrowser(r.props.children))); } pushEndInstance(target, target, 'title', r.props); break; diff --git a/packages/react-dom-bindings/src/server/escapeTextForBrowser.js b/packages/react-dom-bindings/src/server/escapeTextForBrowser.js index 0c8abd00938c5..90407972ba02a 100644 --- a/packages/react-dom-bindings/src/server/escapeTextForBrowser.js +++ b/packages/react-dom-bindings/src/server/escapeTextForBrowser.js @@ -28,6 +28,8 @@ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * @flow */ // code copied and modified from escape-html @@ -103,12 +105,12 @@ function escapeHtml(string) { * @param {*} text Text value to escape. * @return {string} An escaped string. */ -function escapeTextForBrowser(text) { +function escapeTextForBrowser(text: string | number | boolean): string { if (typeof text === 'boolean' || typeof text === 'number') { // this shortcircuit helps perf for types that we know will never have // special characters, especially given that this function is used often // for numeric dom ids. - return '' + text; + return '' + (text: any); } return escapeHtml(text); } diff --git a/packages/react-dom/src/__tests__/ReactDOMFizzServerBrowser-test.js b/packages/react-dom/src/__tests__/ReactDOMFizzServerBrowser-test.js index e3d5808dc1080..1b1357b0e9cea 100644 --- a/packages/react-dom/src/__tests__/ReactDOMFizzServerBrowser-test.js +++ b/packages/react-dom/src/__tests__/ReactDOMFizzServerBrowser-test.js @@ -484,4 +484,22 @@ describe('ReactDOMFizzServerBrowser', () => { expect(errors).toEqual(['uh oh', 'uh oh']); }); + + // https://github.com/facebook/react/pull/25534/files - fix transposed escape functions + // @gate enableFloat + it('should encode title properly', async () => { + const stream = await ReactDOMFizzServer.renderToReadableStream( + +
+