react icon indicating copy to clipboard operation
react copied to clipboard

Bug: `renderToPipeableStream()` emit mysterious mojibake whitespace chars in the result

Open tetsuharuohzeki opened this issue 2 years ago • 2 comments

renderToPipeableStream() emit mojibake whitespace chars in its result. This would sometimes breaks the final generated html.

React version: 18.2.0

Steps To Reproduce

Run this test case with jest.

import { PassThrough } from 'node:stream';
import { renderToPipeableStream } from 'react-dom/server';

const element = (
    <html lang="ja">
        <head>
            <meta charSet="utf-8" />
            <title>吾輩は猫である</title>
        </head>
        <body>
            <p>
                どこで生れたかとんと見当がつかぬ。何でも薄暗いじめじめした所でニャーニャー泣いていた事だけは記憶している。吾輩はここで始めて人間というものを見た。しかもあとで聞くとそれは書生という人間中で一番獰悪な種族であったそうだ。この書生というのは時々我々を捕えて煮て食うという話である。しかしその当時は何という考もなかったから別段恐しいとも思わなかった。ただ彼の掌に載せられてスーと持ち上げられた時何だかフワフワした感じがあったばかりである。掌の上で少し落ちついて書生の顔を見たのがいわゆる人間というものの見始であろう。この時妙なものだと思った感じが今でも残っている。第一毛をもって装飾されべきはずの顔がつるつるしてまるで薬缶だ。その後猫にもだいぶ逢ったがこんな片輪には一度も出会わした事がない。のみならず顔の真中があまりに突起している。そうしてその穴の中から時々ぷうぷうと煙を吹く。どうも咽せぽくて実に弱った。これが人間の飲む煙草というものである事はようやくこの頃知った。
            </p>
            <p>
                この書生の掌の裏でしばらくはよい心持に坐っておったが、しばらくすると非常な速力で運転し始めた。書生が動くのか自分だけが動くのか分らないが無暗に眼が廻る。胸が悪くなる。到底助からないと思っていると、どさりと音がして眼から火が出た。それまでは記憶しているがあとは何の事やらいくら考え出そうとしても分らない。
            </p>
            <p>
                ふと気が付いて見ると書生はいない。たくさんおった兄弟が一疋も見えぬ。肝心の母親さえ姿を隠してしまった。その上今までの所とは違って無暗に明るい。眼を明いていられぬくらいだ。はてな何でも容子がおかしいと、のそのそ這い出して見ると非常に痛い。吾輩は藁の上から急に笹原の中へ棄てられたのである。
            </p>
        </body>
    </html>
);

test('renderToPipeableStream', async () => {
    const onStreamReady = new Promise((resolve, reject) => {
        const stream = renderToPipeableStream(element, {
            onAllReady() {
                resolve(stream);
            },
            onError(err) {
                reject(err);
            },
        });
    });

    const renderingStream = await onStreamReady;

    const sink = new PassThrough();
    const connected = renderingStream.pipe(sink);

    const result = [];
    for await (const chunk of connected) {
        if (typeof chunk === 'string') {
            result.push(chunk);
        } else {
            const txt = String(chunk);
            result.push(txt);
        }
    }

    const actual = result.join('');
    expect(actual).toMatchSnapshot();
});

The current behavior

The above testcase generate this result:

"<!DOCTYPE html><html lang="ja"><head><meta charSet="utf-8"/><title>吾輩は猫である</title></head><body><p>どこで生れたかとんと見当がつかぬ。何でも薄暗いじめじめした所でニャーニャー泣いていた事だけは記憶している。吾輩はここで始めて人間というものを見た。しかもあとで聞くとそれは書生という人間中で一番獰悪な種族であったそうだ。この書生というのは時々我々を捕えて煮て食うという話である。しかしその当時は何という考もなかったから別段恐しいとも思わなかった。ただ彼の掌に載せられてスーと持ち上げられた時何だかフワフワした感じがあったばかりである。掌の上で少し落ちついて書生の顔を見たのがいわゆる人間というものの見始であろう。この時妙なものだと思った感じが今でも残っている。第一毛をもって装飾されべきはずの顔がつるつるしてまるで薬缶だ。その後猫にもだいぶ逢ったがこんな片輪には一度も出会わした事がない。のみならず顔の真中があまりに突起している。そうしてその穴の中から時々ぷうぷうと煙を吹く。どうも咽せぽくて実に弱った。これが人間の飲む煙草というものである事はようやくこの頃知った。</p><p>この書生の掌の裏でしばらくはよい心持に坐っておったが、しばらくすると非常な速力で運転し始めた。書生が動くのか自分だけが動くのか分らないが無暗に眼が廻る。胸が悪くなる。到底助からないと思っていると、どさりと音がして眼から火が出た。それまでは記憶しているがあとは何の事やらいくら考え出そうとしても分らない。</p><p>ふと気が付いて見ると書生はいない。たくさんおった兄弟が一疋も見えぬ。肝心の母親さえ姿を隠してしまった。その上今まで��の所とは違って無暗に明るい。眼を明いていられぬくらいだ。はてな何でも容子がおかしいと、のそのそ這い出して見ると非常に痛い。吾輩は藁の上から急に笹原の中へ棄てられたのである。</p></body></html>"

The expected behavior

The current behavior's result contains その上今まで��の所とは違って無暗に明るい. But we expect this sentence should be その上今までの所とは違って無暗に明るい.

So renderToPipeableStream() should not emit mysterious whitespace chars.

tetsuharuohzeki avatar Jul 25 '22 13:07 tetsuharuohzeki

I confirmed:

  • This bug is not reproducible with renderToStaticNodeStream().
  • This bug is not reproducible in v18.0.0.
    • But this bug is reproducble from v18.1.0.

So I guess some regressions happens in this range. https://github.com/facebook/react/compare/v18.0.0...v18.1.0

tetsuharuohzeki avatar Jul 25 '22 13:07 tetsuharuohzeki

This bug may be related to #24592

tetsuharuohzeki avatar Jul 25 '22 13:07 tetsuharuohzeki

Thanks for the clear repro case!

sophiebits avatar Feb 24 '23 06:02 sophiebits

(I am guessing #24592 is not related, since this issue seems to be with non-ASCII characters and I don't believe that one is.)

sophiebits avatar Feb 24 '23 06:02 sophiebits

@sophiebits Thank you!

tetsuharuohzeki avatar Feb 25 '23 14:02 tetsuharuohzeki