130
startInlineScript: PrecomputedChunk,
131
instructions: InstructionState,
132
133
- // state for outputting CSP nonce
134
- nonce: string | void,
135
-
133
// state for data streaming format
137
- externalRuntimeConfig: BootstrapScriptDescriptor | null,
134
+ externalRuntimeScript: null | ExternalRuntimeScript,
135
136
// preamble and postamble chunks and state
137
htmlChunks: null | Array<Chunk | PrecomputedChunk>,
193
src: string,
194
integrity?: string,
195
};
196
+export type ExternalRuntimeScript = {
197
+ src: string,
198
+ chunks: Array<Chunk | PrecomputedChunk>,
199
+};
200
// Allows us to keep track of what we've already written so we can refer back to it.
201
// if passed externalRuntimeConfig and the enableFizzExternalRuntime feature flag
202
// is set, the server will send instructions via data attributes (instead of inline scripts)
216
'<script nonce="' + escapeTextForBrowser(nonce) + '">',
217
);
218
const bootstrapChunks: Array<Chunk | PrecomputedChunk> = [];
218
- let externalRuntimeDesc = null;
219
+ let externalRuntimeScript: null | ExternalRuntimeScript = null;
220
let streamingFormat = ScriptStreamingFormat;
221
if (bootstrapScriptContent !== undefined) {
222
bootstrapChunks.push(
234
if (externalRuntimeConfig !== undefined) {
235
streamingFormat = DataStreamingFormat;
236
if (typeof externalRuntimeConfig === 'string') {
236
- externalRuntimeDesc = {
237
+ externalRuntimeScript = {
238
src: externalRuntimeConfig,
238
- integrity: undefined,
239
+ chunks: [],
240
};
241
+ pushScriptImpl(externalRuntimeScript.chunks, {
242
+ src: externalRuntimeConfig,
243
+ async: true,
244
+ integrity: undefined,
245
+ nonce: nonce,
246
+ });
247
} else {
241
- externalRuntimeDesc = externalRuntimeConfig;
248
+ externalRuntimeScript = {
249
+ src: externalRuntimeConfig.src,
250
+ chunks: [],
251
+ };
252
+ pushScriptImpl(externalRuntimeScript.chunks, {
253
+ src: externalRuntimeConfig.src,
254
+ async: true,
255
+ integrity: externalRuntimeConfig.integrity,
256
+ nonce: nonce,
257
+ });
258
}
259
}
260
}
323
streamingFormat,
324
startInlineScript: inlineScriptWithNonce,
325
instructions: NothingSent,
310
- externalRuntimeConfig: externalRuntimeDesc,
326
+ externalRuntimeScript,
327
htmlChunks: null,
328
headChunks: null,
329
hasBody: false,
1309
// to emit anything. It's always used.
1310
if (
1311
(responseState.instructions & SentFormReplayingRuntime) === NothingSent &&
1296
- (!enableFizzExternalRuntime || !responseState.externalRuntimeConfig)
1312
+ (!enableFizzExternalRuntime || !responseState.externalRuntimeScript)
1313
) {
1314
responseState.instructions |= SentFormReplayingRuntime;
1315
responseState.bootstrapChunks.unshift(
4094
if (
4095
enableFizzExternalRuntime &&
4096
!willFlushAllSegments &&
4081
- responseState.externalRuntimeConfig
4097
+ responseState.externalRuntimeScript
4098
) {
4099
// If the root segment is incomplete due to suspended tasks
4100
// (e.g. willFlushAllSegments = false) and we are using data
4101
// streaming format, ensure the external runtime is sent.
4102
// (User code could choose to send this even earlier by calling
4103
// preinit(...), if they know they will suspend).
4088
- const {src, integrity} = responseState.externalRuntimeConfig;
4089
- internalPreinitScript(resources, src, integrity, responseState.nonce);
4104
+ const {src, chunks} = responseState.externalRuntimeScript;
4105
+ internalPreinitScript(resources, src, chunks);
4106
}
4107
4108
const htmlChunks = responseState.htmlChunks;
5378
}
5379
}
5380
5365
-// This method is trusted. It must only be called from within this codebase and it assumes the arguments
5366
-// conform to the types because no user input is being passed in. It also assumes that it is being called as
5367
-// part of a work or flush loop and therefore does not need to request Fizz to flush Resources.
5381
function internalPreinitScript(
5382
resources: Resources,
5383
src: string,
5371
- integrity: ?string,
5372
- nonce: ?string,
5384
+ chunks: Array<Chunk | PrecomputedChunk>,
5385
): void {
5386
const key = getResourceKey('script', src);
5387
let resource = resources.scriptsMap.get(key);
5388
if (!resource) {
5389
resource = {
5390
type: 'script',
5379
- chunks: [],
5391
+ chunks,
5392
state: NoState,
5393
props: null,
5394
};
5395
resources.scriptsMap.set(key, resource);
5396
resources.scripts.add(resource);
5385
- pushScriptImpl(resource.chunks, {
5386
- async: true,
5387
- src,
5388
- integrity,
5389
- nonce,
5390
- });
5397
}
5398
return;
5399
}