Skip to content

Commit a9a1864

Browse files
committed
Address code review feedback
- Remove debug console.error statements from streamingUtils.ts - Add documentation explaining why consoleReplay() is used instead of buildConsoleReplay() in streaming contexts (unwrapped JS for JSON payloads vs wrapped for HTML) - Use idiomatic TypeScript optional parameter syntax (nonce?: string) - Add comprehensive test coverage for numberOfMessagesToSkip and customConsoleHistory parameters
1 parent 328cbde commit a9a1864

File tree

3 files changed

+53
-7
lines changed

3 files changed

+53
-7
lines changed

packages/react-on-rails-pro/src/streamingUtils.ts

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -113,14 +113,12 @@ export const transformRenderStreamChunksToResultObject = (renderState: StreamRen
113113
transform(chunk: Buffer, _, callback) {
114114
const htmlChunk = chunk.toString();
115115
// Get unwrapped console replay JavaScript (not wrapped in <script> tags)
116+
// We use consoleReplay() instead of buildConsoleReplay() because streaming
117+
// contexts handle script tag wrapping separately (e.g., with CSP nonces).
118+
// This returns pure JavaScript without wrapping, which is then embedded
119+
// into the result object JSON payload.
116120
const consoleReplayScript = consoleReplay(previouslyReplayedConsoleMessages, consoleHistory);
117121

118-
// DEBUG: Log to verify we're using the unwrapped version
119-
if (consoleReplayScript && consoleReplayScript.startsWith('<script')) {
120-
console.error('ERROR: Console replay is wrapped when it should be unwrapped!');
121-
console.error('First 100 chars:', consoleReplayScript.substring(0, 100));
122-
}
123-
124122
previouslyReplayedConsoleMessages = consoleHistory?.length || 0;
125123
const jsonChunk = JSON.stringify(createResultObject(htmlChunk, consoleReplayScript, renderState));
126124
this.push(`${jsonChunk}\n`);

packages/react-on-rails/src/buildConsoleReplay.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ export function consoleReplay(
5757
export default function buildConsoleReplay(
5858
numberOfMessagesToSkip = 0,
5959
customConsoleHistory: (typeof console)['history'] | undefined = undefined,
60-
nonce: string | undefined = undefined,
60+
nonce?: string,
6161
): string {
6262
const consoleReplayJS = consoleReplay(numberOfMessagesToSkip, customConsoleHistory);
6363
if (consoleReplayJS.length === 0) {

packages/react-on-rails/tests/buildConsoleReplay.test.js

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,4 +123,52 @@ console.warn.apply(console, ["other message","{\\"c\\":3,\\"d\\":4}"]);
123123
// Verify the dangerous parts (quotes and parens) are removed
124124
expect(actual).not.toMatch(/nonce="[^"]*"[^>]*onload=/);
125125
});
126+
127+
it('consoleReplay skips specified number of messages', () => {
128+
console.history = [
129+
{ arguments: ['skip 1'], level: 'log' },
130+
{ arguments: ['skip 2'], level: 'log' },
131+
{ arguments: ['keep 1'], level: 'log' },
132+
{ arguments: ['keep 2'], level: 'warn' },
133+
];
134+
const actual = consoleReplay(2); // Skip first 2 messages
135+
136+
// Should not contain skipped messages
137+
expect(actual).not.toContain('skip 1');
138+
expect(actual).not.toContain('skip 2');
139+
140+
// Should contain kept messages
141+
expect(actual).toContain('console.log.apply(console, ["keep 1"]);');
142+
expect(actual).toContain('console.warn.apply(console, ["keep 2"]);');
143+
});
144+
145+
it('consoleReplay uses custom console history when provided', () => {
146+
console.history = [{ arguments: ['ignored'], level: 'log' }];
147+
const customHistory = [
148+
{ arguments: ['custom message 1'], level: 'warn' },
149+
{ arguments: ['custom message 2'], level: 'error' },
150+
];
151+
const actual = consoleReplay(0, customHistory);
152+
153+
// Should not contain global console.history
154+
expect(actual).not.toContain('ignored');
155+
156+
// Should contain custom history
157+
expect(actual).toContain('console.warn.apply(console, ["custom message 1"]);');
158+
expect(actual).toContain('console.error.apply(console, ["custom message 2"]);');
159+
});
160+
161+
it('consoleReplay combines numberOfMessagesToSkip with custom history', () => {
162+
const customHistory = [
163+
{ arguments: ['skip this'], level: 'log' },
164+
{ arguments: ['keep this'], level: 'warn' },
165+
];
166+
const actual = consoleReplay(1, customHistory);
167+
168+
// Should skip first message
169+
expect(actual).not.toContain('skip this');
170+
171+
// Should keep second message
172+
expect(actual).toContain('console.warn.apply(console, ["keep this"]);');
173+
});
126174
});

0 commit comments

Comments
 (0)