Skip to content

Commit 1c11d72

Browse files
committed
Refactor
1 parent a3259a0 commit 1c11d72

File tree

8 files changed

+90
-53
lines changed

8 files changed

+90
-53
lines changed

packages/react-dom-bindings/src/server/ReactFizzConfigDOM.js

Lines changed: 68 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,8 @@ export type RenderState = {
147147
// inline script streaming format, unused if using external runtime / data
148148
startInlineScript: PrecomputedChunk,
149149

150+
startInlineStyle: PrecomputedChunk,
151+
150152
// the preamble must always flush before resuming, so all these chunks must
151153
// be null or empty when resuming.
152154

@@ -243,6 +245,8 @@ if (__DEV__) {
243245
Object.freeze(PRELOAD_NO_CREDS);
244246
}
245247

248+
// what about this?
249+
246250
// Per response, global state that is not contextual to the rendering subtree.
247251
// This is resumable and therefore should be serializable.
248252
export type ResumableState = {
@@ -307,6 +311,8 @@ const scriptIntegirty = stringToPrecomputedChunk(' integrity="');
307311
const scriptCrossOrigin = stringToPrecomputedChunk(' crossorigin="');
308312
const endAsyncScript = stringToPrecomputedChunk(' async=""></script>');
309313

314+
const startInlineStyle = stringToPrecomputedChunk('<style');
315+
310316
/**
311317
* This escaping function is designed to work with with inline scripts where the entire
312318
* contents are escaped. Because we know we are escaping the entire script we can avoid for instance
@@ -365,17 +371,31 @@ if (__DEV__) {
365371
// is set, the server will send instructions via data attributes (instead of inline scripts)
366372
export function createRenderState(
367373
resumableState: ResumableState,
368-
nonce: string | void,
374+
nonce:
375+
| string
376+
| {
377+
script?: string,
378+
style?: string,
379+
}
380+
| void,
369381
externalRuntimeConfig: string | BootstrapScriptDescriptor | void,
370382
importMap: ImportMap | void,
371383
onHeaders: void | ((headers: HeadersDescriptor) => void),
372384
maxHeadersLength: void | number,
373385
): RenderState {
386+
const nonceScript = typeof nonce === 'string' ? nonce : nonce && nonce.script;
374387
const inlineScriptWithNonce =
375-
nonce === undefined
388+
nonceScript === undefined
376389
? startInlineScript
377390
: stringToPrecomputedChunk(
378-
'<script nonce="' + escapeTextForBrowser(nonce) + '"',
391+
'<script nonce="' + escapeTextForBrowser(nonceScript) + '"',
392+
);
393+
const nonceStyle = nonce && nonce.style;
394+
const inlineStyleWithNonce =
395+
nonceStyle === undefined
396+
? startInlineStyle
397+
: stringToPrecomputedChunk(
398+
'<style nonce="' + escapeTextForBrowser(nonceStyle) + '"',
379399
);
380400
const idPrefix = resumableState.idPrefix;
381401

@@ -403,7 +423,7 @@ export function createRenderState(
403423
src: externalRuntimeConfig,
404424
async: true,
405425
integrity: undefined,
406-
nonce: nonce,
426+
nonce: nonceScript,
407427
});
408428
} else {
409429
externalRuntimeScript = {
@@ -414,7 +434,7 @@ export function createRenderState(
414434
src: externalRuntimeConfig.src,
415435
async: true,
416436
integrity: externalRuntimeConfig.integrity,
417-
nonce: nonce,
437+
nonce: nonceScript,
418438
});
419439
}
420440
}
@@ -459,6 +479,7 @@ export function createRenderState(
459479
segmentPrefix: stringToPrecomputedChunk(idPrefix + 'S:'),
460480
boundaryPrefix: stringToPrecomputedChunk(idPrefix + 'B:'),
461481
startInlineScript: inlineScriptWithNonce,
482+
startInlineStyle: inlineStyleWithNonce,
462483
preamble: createPreambleState(),
463484

464485
externalRuntimeScript: externalRuntimeScript,
@@ -500,7 +521,10 @@ export function createRenderState(
500521
moduleScripts: new Map(),
501522
},
502523

503-
nonce,
524+
nonce: {
525+
script: nonceScript,
526+
style: nonceStyle,
527+
},
504528
// like a module global for currently rendering boundary
505529
hoistableState: null,
506530
stylesToHoist: false,
@@ -539,10 +563,10 @@ export function createRenderState(
539563
stringToChunk(escapeTextForBrowser(src)),
540564
attributeEnd,
541565
);
542-
if (nonce) {
566+
if (nonceScript) {
543567
bootstrapChunks.push(
544568
scriptNonce,
545-
stringToChunk(escapeTextForBrowser(nonce)),
569+
stringToChunk(escapeTextForBrowser(nonceScript)),
546570
attributeEnd,
547571
);
548572
}
@@ -571,7 +595,7 @@ export function createRenderState(
571595
const props: PreloadModuleProps = ({
572596
rel: 'modulepreload',
573597
fetchPriority: 'low',
574-
nonce,
598+
nonce: nonceScript,
575599
}: any);
576600
if (typeof scriptConfig === 'string') {
577601
props.href = src = scriptConfig;
@@ -596,10 +620,10 @@ export function createRenderState(
596620
stringToChunk(escapeTextForBrowser(src)),
597621
attributeEnd,
598622
);
599-
if (nonce) {
623+
if (nonceScript) {
600624
bootstrapChunks.push(
601625
scriptNonce,
602-
stringToChunk(escapeTextForBrowser(nonce)),
626+
stringToChunk(escapeTextForBrowser(nonceScript)),
603627
attributeEnd,
604628
);
605629
}
@@ -2882,11 +2906,11 @@ function pushLink(
28822906
// to create a StyleQueue
28832907
if (!styleQueue) {
28842908
styleQueue = {
2909+
start: renderState.startInlineStyle,
28852910
precedence: stringToChunk(escapeTextForBrowser(precedence)),
28862911
rules: ([]: Array<Chunk | PrecomputedChunk>),
28872912
hrefs: ([]: Array<Chunk | PrecomputedChunk>),
28882913
sheets: (new Map(): Map<string, StylesheetResource>),
2889-
nonce: props.nonce,
28902914
};
28912915
renderState.styles.set(precedence, styleQueue);
28922916
}
@@ -3091,21 +3115,29 @@ function pushStyle(
30913115
// This is the first time we've encountered this precedence we need
30923116
// to create a StyleQueue.
30933117
styleQueue = {
3118+
start: renderState.startInlineStyle,
30943119
precedence: stringToChunk(escapeTextForBrowser(precedence)),
3095-
rules: pushStyleContents(([]: Array<Chunk | PrecomputedChunk>), props),
3096-
hrefs: [stringToChunk(escapeTextForBrowser(href))],
3120+
rules: ([]: Array<Chunk | PrecomputedChunk>),
3121+
hrefs: ([]: Array<Chunk | PrecomputedChunk>),
30973122
sheets: (new Map(): Map<string, StylesheetResource>),
3098-
nonce: nonce,
30993123
};
31003124
renderState.styles.set(precedence, styleQueue);
3101-
} else if (nonce === styleQueue.nonce) {
3102-
// We have seen this precedence before and need to track this href
3125+
}
3126+
3127+
const nonceStyle = renderState.nonce.style;
3128+
if (nonceStyle ? nonceStyle === nonce : !nonce) {
31033129
styleQueue.hrefs.push(stringToChunk(escapeTextForBrowser(href)));
31043130
pushStyleContents(styleQueue.rules, props);
31053131
} else if (__DEV__) {
3106-
console.error(
3107-
"React encountered a hoistable style tag with nonce. It doesn't match the previously encountered nonce. They have to be the same",
3108-
);
3132+
if (nonceStyle) {
3133+
console.error(
3134+
"React encountered a hoistable style tag with nonce. It doesn't match the previously encountered nonce. They have to be the same.",
3135+
);
3136+
} else {
3137+
console.error(
3138+
'React encountered a hoistable style tag with nonce. The nonce was not passed to the render call though.',
3139+
);
3140+
}
31093141
}
31103142
}
31113143
if (styleQueue) {
@@ -3198,7 +3230,7 @@ function pushStyleImpl(
31983230
function pushStyleContents(
31993231
target: Array<Chunk | PrecomputedChunk>,
32003232
props: Object,
3201-
): Array<Chunk | PrecomputedChunk> {
3233+
): void {
32023234
let children = null;
32033235
let innerHTML = null;
32043236
for (const propKey in props) {
@@ -3232,7 +3264,7 @@ function pushStyleContents(
32323264
target.push(stringToChunk(escapeStyleTextContent(child)));
32333265
}
32343266
pushInnerHTML(target, innerHTML, children);
3235-
return target;
3267+
return;
32363268
}
32373269

32383270
function pushImg(
@@ -5155,11 +5187,10 @@ function escapeJSObjectForInstructionScripts(input: Object): string {
51555187
}
51565188

51575189
const lateStyleTagResourceOpen1 = stringToPrecomputedChunk(
5158-
'<style media="not all" data-precedence="',
5190+
' media="not all" data-precedence="',
51595191
);
5160-
const lateStyleTagResourceOpen2 = stringToPrecomputedChunk('" nonce="');
5161-
const lateStyleTagResourceOpen3 = stringToPrecomputedChunk('" data-href="');
5162-
const lateStyleTagResourceOpen4 = stringToPrecomputedChunk('">');
5192+
const lateStyleTagResourceOpen2 = stringToPrecomputedChunk('" data-href="');
5193+
const lateStyleTagResourceOpen3 = stringToPrecomputedChunk('">');
51635194
const lateStyleTagTemplateClose = stringToPrecomputedChunk('</style>');
51645195

51655196
// Tracks whether the boundary currently flushing is flushign style tags or has any
@@ -5175,7 +5206,6 @@ function flushStyleTagsLateForBoundary(
51755206
) {
51765207
const rules = styleQueue.rules;
51775208
const hrefs = styleQueue.hrefs;
5178-
const nonce = styleQueue.nonce;
51795209
if (__DEV__) {
51805210
if (rules.length > 0 && hrefs.length === 0) {
51815211
console.error(
@@ -5185,19 +5215,16 @@ function flushStyleTagsLateForBoundary(
51855215
}
51865216
let i = 0;
51875217
if (hrefs.length) {
5218+
writeChunk(this, styleQueue.start);
51885219
writeChunk(this, lateStyleTagResourceOpen1);
51895220
writeChunk(this, styleQueue.precedence);
5190-
if (nonce) {
5191-
writeChunk(this, lateStyleTagResourceOpen2);
5192-
writeChunk(this, stringToChunk(escapeTextForBrowser(nonce)));
5193-
}
5194-
writeChunk(this, lateStyleTagResourceOpen3);
5221+
writeChunk(this, lateStyleTagResourceOpen2);
51955222
for (; i < hrefs.length - 1; i++) {
51965223
writeChunk(this, hrefs[i]);
51975224
writeChunk(this, spaceSeparator);
51985225
}
51995226
writeChunk(this, hrefs[i]);
5200-
writeChunk(this, lateStyleTagResourceOpen4);
5227+
writeChunk(this, lateStyleTagResourceOpen3);
52015228
for (i = 0; i < rules.length; i++) {
52025229
writeChunk(this, rules[i]);
52035230
}
@@ -5281,13 +5308,10 @@ function flushStyleInPreamble(
52815308
stylesheet.state = PREAMBLE;
52825309
}
52835310

5284-
const styleTagResourceOpen1 = stringToPrecomputedChunk(
5285-
'<style data-precedence="',
5286-
);
5287-
const styleTagResourceOpen2 = stringToPrecomputedChunk('" nonce="');
5288-
const styleTagResourceOpen3 = stringToPrecomputedChunk('" data-href="');
5311+
const styleTagResourceOpen1 = stringToPrecomputedChunk(' data-precedence="');
5312+
const styleTagResourceOpen2 = stringToPrecomputedChunk('" data-href="');
52895313
const spaceSeparator = stringToPrecomputedChunk(' ');
5290-
const styleTagResourceOpen4 = stringToPrecomputedChunk('">');
5314+
const styleTagResourceOpen3 = stringToPrecomputedChunk('">');
52915315

52925316
const styleTagResourceClose = stringToPrecomputedChunk('</style>');
52935317

@@ -5302,27 +5326,23 @@ function flushStylesInPreamble(
53025326

53035327
const rules = styleQueue.rules;
53045328
const hrefs = styleQueue.hrefs;
5305-
const nonce = styleQueue.nonce;
53065329
// If we don't emit any stylesheets at this precedence we still need to maintain the precedence
53075330
// order so even if there are no rules for style tags at this precedence we emit an empty style
53085331
// tag with the data-precedence attribute
53095332
if (!hasStylesheets || hrefs.length) {
5333+
writeChunk(this, styleQueue.start);
53105334
writeChunk(this, styleTagResourceOpen1);
53115335
writeChunk(this, styleQueue.precedence);
5312-
if (nonce) {
5313-
writeChunk(this, styleTagResourceOpen2);
5314-
writeChunk(this, stringToChunk(escapeTextForBrowser(nonce)));
5315-
}
53165336
let i = 0;
53175337
if (hrefs.length) {
5318-
writeChunk(this, styleTagResourceOpen3);
5338+
writeChunk(this, styleTagResourceOpen2);
53195339
for (; i < hrefs.length - 1; i++) {
53205340
writeChunk(this, hrefs[i]);
53215341
writeChunk(this, spaceSeparator);
53225342
}
53235343
writeChunk(this, hrefs[i]);
53245344
}
5325-
writeChunk(this, styleTagResourceOpen4);
5345+
writeChunk(this, styleTagResourceOpen3);
53265346
for (i = 0; i < rules.length; i++) {
53275347
writeChunk(this, rules[i]);
53285348
}
@@ -6076,11 +6096,11 @@ export type HoistableState = {
60766096
};
60776097

60786098
export type StyleQueue = {
6099+
start: PrecomputedChunk,
60796100
precedence: Chunk | PrecomputedChunk,
60806101
rules: Array<Chunk | PrecomputedChunk>,
60816102
hrefs: Array<Chunk | PrecomputedChunk>,
60826103
sheets: Map<string, StylesheetResource>,
6083-
nonce: ?string,
60846104
};
60856105

60866106
export function createHoistableState(): HoistableState {
@@ -6528,11 +6548,11 @@ function preinitStyle(
65286548
// to create a StyleQueue
65296549
if (!styleQueue) {
65306550
styleQueue = {
6551+
start: renderState.startInlineStyle,
65316552
precedence: stringToChunk(escapeTextForBrowser(precedence)),
65326553
rules: ([]: Array<Chunk | PrecomputedChunk>),
65336554
hrefs: ([]: Array<Chunk | PrecomputedChunk>),
65346555
sheets: (new Map(): Map<string, StylesheetResource>),
6535-
nonce: options ? options.nonce : undefined,
65366556
};
65376557
renderState.styles.set(precedence, styleQueue);
65386558
}

packages/react-dom-bindings/src/server/ReactFizzConfigDOMLegacy.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ export type RenderState = {
4747
segmentPrefix: PrecomputedChunk,
4848
boundaryPrefix: PrecomputedChunk,
4949
startInlineScript: PrecomputedChunk,
50+
startInlineStyle: PrecomputedChunk,
5051
preamble: PreambleState,
5152
externalRuntimeScript: null | any,
5253
bootstrapChunks: Array<Chunk | PrecomputedChunk>,
@@ -99,6 +100,7 @@ export function createRenderState(
99100
segmentPrefix: renderState.segmentPrefix,
100101
boundaryPrefix: renderState.boundaryPrefix,
101102
startInlineScript: renderState.startInlineScript,
103+
startInlineStyle: renderState.startInlineStyle,
102104
preamble: renderState.preamble,
103105
externalRuntimeScript: renderState.externalRuntimeScript,
104106
bootstrapChunks: renderState.bootstrapChunks,

packages/react-dom/src/__tests__/ReactDOMFizzServer-test.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10294,6 +10294,7 @@ describe('ReactDOMFizzServer', () => {
1029410294
precedence="default"
1029510295
nonce={CSPnonce}>{`.bar { background-color: blue; }`}</style>
1029610296
</>,
10297+
{nonce: {style: CSPnonce}},
1029710298
);
1029810299
pipe(writable);
1029910300
});
@@ -10329,11 +10330,12 @@ describe('ReactDOMFizzServer', () => {
1032910330
precedence="default"
1033010331
nonce={`${CSPnonce}${CSPnonce}`}>{`.bar { background-color: blue; }`}</style>
1033110332
</>,
10333+
{nonce: {style: CSPnonce}},
1033210334
);
1033310335
pipe(writable);
1033410336
});
1033510337
assertConsoleErrorDev([
10336-
"React encountered a hoistable style tag with nonce. It doesn't match the previously encountered nonce. They have to be the same",
10338+
"React encountered a hoistable style tag with nonce. It doesn't match the previously encountered nonce. They have to be the same.",
1033710339
]);
1033810340
expect(getVisibleChildren(document)).toEqual(
1033910341
<html>

packages/react-dom/src/__tests__/ReactDOMFloat-test.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8624,6 +8624,7 @@ background-color: green;
86248624
</Suspense>
86258625
</body>
86268626
</html>,
8627+
{nonce: {style: nonce}},
86278628
).pipe(writable);
86288629
});
86298630

packages/react-dom/src/server/ReactDOMFizzServerBrowser.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,12 @@ ensureCorrectIsomorphicReactVersion();
4343
type Options = {
4444
identifierPrefix?: string,
4545
namespaceURI?: string,
46-
nonce?: string,
46+
nonce?:
47+
| string
48+
| {
49+
script?: string,
50+
style?: string,
51+
},
4752
bootstrapScriptContent?: string,
4853
bootstrapScripts?: Array<string | BootstrapScriptDescriptor>,
4954
bootstrapModules?: Array<string | BootstrapScriptDescriptor>,

packages/react-dom/src/server/ReactDOMFizzServerBun.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,10 @@ ensureCorrectIsomorphicReactVersion();
3737
type Options = {
3838
identifierPrefix?: string,
3939
namespaceURI?: string,
40-
nonce?: string,
40+
nonce?: string | {
41+
script?: string,
42+
style?: string,
43+
},
4144
bootstrapScriptContent?: string,
4245
bootstrapScripts?: Array<string | BootstrapScriptDescriptor>,
4346
bootstrapModules?: Array<string | BootstrapScriptDescriptor>,

0 commit comments

Comments
 (0)