153
preloadChunks: Array<Chunk | PrecomputedChunk>,
154
hoistableChunks: Array<Chunk | PrecomputedChunk>,
155
156
+ // Module-global-like reference for flushing/hoisting state of style resources
157
+ // We need to track whether the current request has flushed any style resources
158
+ // without sending an instruction to hoist them. we do that here
159
+ stylesToHoist: boolean,
160
+
161
// We allow the legacy renderer to extend this object.
162
163
...
305
preconnectChunks: [],
306
preloadChunks: [],
307
hoistableChunks: [],
308
+ stylesToHoist: false,
309
};
310
}
311
1427
resource = {
1428
type: 'stylesheet',
1429
chunks: ([]: Array<Chunk | PrecomputedChunk>),
1424
- state: resources.boundaryResources ? Blocked : NoState,
1430
+ state: NoState,
1431
props: resourceProps,
1432
};
1433
resources.stylesMap.set(key, resource);
1438
if (!precedenceSet) {
1439
precedenceSet = new Set();
1440
resources.precedences.set(precedence, precedenceSet);
1441
+ const emptyStyleResource = {
1442
+ type: 'style',
1443
+ chunks: ([]: Array<Chunk | PrecomputedChunk>),
1444
+ state: NoState,
1445
+ props: {
1446
+ precedence,
1447
+ hrefs: ([]: Array<string>),
1448
+ },
1449
+ };
1450
+ precedenceSet.add(emptyStyleResource);
1451
+ if (__DEV__) {
1452
+ if (resources.stylePrecedences.has(precedence)) {
1453
+ console.error(
1454
+ 'React constructed an empty style resource when a style resource already exists for this precedence: "%s". This is a bug in React.',
1455
+ precedence,
1456
+ );
1457
+ }
1458
+ }
1459
+ resources.stylePrecedences.set(precedence, emptyStyleResource);
1460
}
1461
precedenceSet.add(resource);
1462
}
1581
return pushStyleImpl(target, props);
1582
}
1583
1584
+ if (__DEV__) {
1585
+ if (href.includes(' ')) {
1586
+ console.error(
1587
+ 'React expected the `href` prop for a <style> tag opting into hoisting semantics using the `precedence` prop to not have any spaces but ecountered spaces instead. using spaces in this prop will cause hydration of this style to fail on the client. The href for the <style> where this ocurred is "%s".',
1588
+ href,
1589
+ );
1590
+ }
1591
+ }
1592
+
1593
const key = getResourceKey('style', href);
1594
let resource = resources.stylesMap.get(key);
1595
if (!resource) {
1562
- resource = {
1563
- type: 'style',
1564
- chunks: ([]: Array<Chunk | PrecomputedChunk>),
1565
- state: resources.boundaryResources ? Blocked : NoState,
1566
- props: styleTagPropsFromRawProps(props),
1567
- };
1568
- resources.stylesMap.set(key, resource);
1569
- if (__DEV__) {
1570
- markAsRenderedResourceDEV(resource, props);
1571
- }
1572
- pushStyleImpl(resource.chunks, resource.props);
1573
-
1574
- let precedenceSet = resources.precedences.get(precedence);
1575
- if (!precedenceSet) {
1576
- precedenceSet = new Set();
1596
+ resource = resources.stylePrecedences.get(precedence);
1597
+ if (!resource) {
1598
+ resource = {
1599
+ type: 'style',
1600
+ chunks: [],
1601
+ state: NoState,
1602
+ props: {
1603
+ precedence,
1604
+ hrefs: [href],
1605
+ },
1606
+ };
1607
+ resources.stylePrecedences.set(precedence, resource);
1608
+ const precedenceSet: Set<StyleResource> = new Set();
1609
+ precedenceSet.add(resource);
1610
+ if (__DEV__) {
1611
+ if (resources.precedences.has(precedence)) {
1612
+ console.error(
1613
+ 'React constructed a new style precedence set when one already exists for this precedence: "%s". This is a bug in React.',
1614
+ precedence,
1615
+ );
1616
+ }
1617
+ }
1618
resources.precedences.set(precedence, precedenceSet);
1619
+ } else {
1620
+ resource.props.hrefs.push(href);
1621
}
1579
- precedenceSet.add(resource);
1622
+ resources.stylesMap.set(key, resource);
1623
if (resources.boundaryResources) {
1624
resources.boundaryResources.add(resource);
1625
}
1626
+ pushStyleContents(resource.chunks, props);
1627
}
1628
1629
if (textEmbedded) {
1684
return null;
1685
}
1686
1687
+function pushStyleContents(
1688
+ target: Array<Chunk | PrecomputedChunk>,
1689
+ props: Object,
1690
+): void {
1691
+ let children = null;
1692
+ let innerHTML = null;
1693
+ for (const propKey in props) {
1694
+ if (hasOwnProperty.call(props, propKey)) {
1695
+ const propValue = props[propKey];
1696
+ if (propValue == null) {
1697
+ continue;
1698
+ }
1699
+ switch (propKey) {
1700
+ case 'children':
1701
+ children = propValue;
1702
+ break;
1703
+ case 'dangerouslySetInnerHTML':
1704
+ innerHTML = propValue;
1705
+ break;
1706
+ }
1707
+ }
1708
+ }
1709
+
1710
+ const child = Array.isArray(children)
1711
+ ? children.length < 2
1712
+ ? children[0]
1713
+ : null
1714
+ : children;
1715
+ if (
1716
+ typeof child !== 'function' &&
1717
+ typeof child !== 'symbol' &&
1718
+ child !== null &&
1719
+ child !== undefined
1720
+ ) {
1721
+ // eslint-disable-next-line react-internal/safe-string-coercion
1722
+ target.push(stringToChunk(escapeTextForBrowser('' + child)));
1723
+ }
1724
+ pushInnerHTML(target, innerHTML, children);
1725
+ return;
1726
+}
1727
+
1728
function pushSelfClosing(
1729
target: Array<Chunk | PrecomputedChunk>,
1730
props: Object,
3016
const completeBoundaryWithStylesScript1FullPartial = stringToPrecomputedChunk(
3017
styleInsertionFunction + '$RR("',
3018
);
3019
+
3020
const completeBoundaryWithStylesScript1Partial =
3021
stringToPrecomputedChunk('$RR("');
3022
const completeBoundaryScript2 = stringToPrecomputedChunk('","');
3041
contentSegmentID: number,
3042
boundaryResources: BoundaryResources,
3043
): boolean {
2958
- let hasStyleDependencies;
3044
+ let requiresStyleInsertion;
3045
if (enableFloat) {
2960
- hasStyleDependencies = hasStyleResourceDependencies(boundaryResources);
3046
+ requiresStyleInsertion = responseState.stylesToHoist;
3047
+ // If necessary stylesheets will be flushed with this instruction.
3048
+ // Any style tags not yet hoisted in the Document will also be hoisted.
3049
+ // We reset this state since after this instruction executes all styles
3050
+ // up to this point will have been hoisted
3051
+ responseState.stylesToHoist = false;
3052
}
3053
const scriptFormat =
3054
!enableFizzExternalRuntime ||
3055
responseState.streamingFormat === ScriptStreamingFormat;
3056
if (scriptFormat) {
3057
writeChunk(destination, responseState.startInlineScript);
2967
- if (enableFloat && hasStyleDependencies) {
3058
+ if (enableFloat && requiresStyleInsertion) {
3059
if (
3060
(responseState.instructions & SentCompleteBoundaryFunction) ===
3061
NothingSent
3087
}
3088
}
3089
} else {
2999
- if (enableFloat && hasStyleDependencies) {
3090
+ if (enableFloat && requiresStyleInsertion) {
3091
writeChunk(destination, completeBoundaryWithStylesData1);
3092
} else {
3093
writeChunk(destination, completeBoundaryData1);
3110
}
3111
writeChunk(destination, responseState.segmentPrefix);
3112
writeChunk(destination, formattedContentID);
3022
- if (enableFloat && hasStyleDependencies) {
3113
+ if (enableFloat && requiresStyleInsertion) {
3114
// Script and data writers must format this differently:
3115
// - script writer emits an array literal, whose string elements are
3116
// escaped for javascript e.g. ["A", "B"]
3305
});
3306
}
3307
3217
-const styleTagTemplateOpen = stringToPrecomputedChunk(
3218
- '<template data-precedence="">',
3308
+const lateStyleTagResourceOpen1 = stringToPrecomputedChunk(
3309
+ '<style media="not all" data-precedence="',
3310
);
3220
-const styleTagTemplateClose = stringToPrecomputedChunk('</template>');
3311
+const lateStyleTagResourceOpen2 = stringToPrecomputedChunk('" data-href="');
3312
+const lateStyleTagResourceOpen3 = stringToPrecomputedChunk('">');
3313
+const lateStyleTagTemplateClose = stringToPrecomputedChunk('</style>');
3314
+
3315
+// Tracks whether the boundary currently flushing is flushign style tags or has any
3316
+// stylesheet dependencies not flushed in the Preamble.
3317
+let currentlyRenderingBoundaryHasStylesToHoist = false;
3318
3222
-// Tracks whether we wrote any late style tags. We use this to determine
3223
-// whether we need to emit a closing template tag after flushing late style tags
3224
-let didWrite = false;
3319
+// Acts as a return value for the forEach execution of style tag flushing.
3320
+let destinationHasCapacity = true;
3321
3322
function flushStyleTagsLateForBoundary(
3323
this: Destination,
3324
resource: StyleResource,
3325
) {
3230
- if (resource.type === 'style' && (resource.state & Flushed) === NoState) {
3231
- if (didWrite === false) {
3232
- // we are going to write so we need to emit the open tag
3233
- didWrite = true;
3234
- writeChunk(this, styleTagTemplateOpen);
3235
- }
3236
- // This <style> tag can be flushed now
3326
+ if (
3327
+ resource.type === 'stylesheet' &&
3328
+ (resource.state & FlushedInPreamble) === NoState
3329
+ ) {
3330
+ currentlyRenderingBoundaryHasStylesToHoist = true;
3331
+ } else if (resource.type === 'style') {
3332
const chunks = resource.chunks;
3238
- for (let i = 0; i < chunks.length; i++) {
3239
- writeChunk(this, chunks[i]);
3333
+ const hrefs = resource.props.hrefs;
3334
+ let i = 0;
3335
+ if (chunks.length) {
3336
+ writeChunk(this, lateStyleTagResourceOpen1);
3337
+ writeChunk(
3338
+ this,
3339
+ stringToChunk(escapeTextForBrowser(resource.props.precedence)),
3340
+ );
3341
+ if (hrefs.length) {
3342
+ writeChunk(this, lateStyleTagResourceOpen2);
3343
+ for (; i < hrefs.length - 1; i++) {
3344
+ writeChunk(this, stringToChunk(escapeTextForBrowser(hrefs[i])));
3345
+ writeChunk(this, spaceSeparator);
3346
+ }
3347
+ writeChunk(this, stringToChunk(escapeTextForBrowser(hrefs[i])));
3348
+ }
3349
+ writeChunk(this, lateStyleTagResourceOpen3);
3350
+ for (i = 0; i < chunks.length; i++) {
3351
+ writeChunk(this, chunks[i]);
3352
+ }
3353
+ destinationHasCapacity = writeChunkAndReturn(
3354
+ this,
3355
+ lateStyleTagTemplateClose,
3356
+ );
3357
+
3358
+ // We wrote style tags for this boundary and we may need to emit a script
3359
+ // to hoist them.
3360
+ currentlyRenderingBoundaryHasStylesToHoist = true;
3361
+
3362
+ // style resources can flush continuously since more rules may be written into
3363
+ // them with new hrefs. Instead of marking it flushed, we simply reset the chunks
3364
+ // and hrefs
3365
+ chunks.length = 0;
3366
+ hrefs.length = 0;
3367
}
3241
- resource.state |= FlushedLate;
3368
}
3369
}
3370
3371
export function writeResourcesForBoundary(
3372
destination: Destination,
3373
boundaryResources: BoundaryResources,
3374
+ responseState: ResponseState,
3375
): boolean {
3249
- didWrite = false;
3376
+ // Reset these on each invocation, they are only safe to read in this function
3377
+ currentlyRenderingBoundaryHasStylesToHoist = false;
3378
+ destinationHasCapacity = true;
3379
+
3380
+ // Flush each Boundary resource
3381
boundaryResources.forEach(flushStyleTagsLateForBoundary, destination);
3251
- if (didWrite) {
3252
- return writeChunkAndReturn(destination, styleTagTemplateClose);
3253
- } else {
3254
- return true;
3382
+ if (currentlyRenderingBoundaryHasStylesToHoist) {
3383
+ responseState.stylesToHoist = true;
3384
}
3385
+ return destinationHasCapacity;
3386
}
3387
3258
-const precedencePlaceholderStart = stringToPrecomputedChunk(
3259
- '<style data-precedence="',
3260
-);
3261
-const precedencePlaceholderEnd = stringToPrecomputedChunk('"></style>');
3262
-
3388
function flushResourceInPreamble<T: Resource>(this: Destination, resource: T) {
3389
if ((resource.state & (Flushed | Blocked)) === NoState) {
3390
const chunks = resource.chunks;
3396
}
3397
3398
function flushResourceLate<T: Resource>(this: Destination, resource: T) {
3274
- if ((resource.state & Flushed) === NoState) {
3399
+ if ((resource.state & (Flushed | Blocked)) === NoState) {
3400
const chunks = resource.chunks;
3401
for (let i = 0; i < chunks.length; i++) {
3402
writeChunk(this, chunks[i]);
3405
}
3406
}
3407
3283
-let didFlush = false;
3408
+// This must always be read after flushing stylesheet styles. we know we will encounter a style resource
3409
+// per precedence and it will be set before ready so we cast this to avoid an extra check at runtime
3410
+let precedenceStyleTagResource: StyleTagResource = (null: any);
3411
+
3412
+// This flags let's us opt out of flushing a placeholder style tag to emit the precedence in the right order.
3413
+// If a stylesheet was flushed then we have the precedence order preserved and only need to emit <style> tags
3414
+// if there are actual chunks to flush
3415
+let didFlushPrecedence = false;
3416
3285
-function flushUnblockedStyle(
3417
+function flushStyleInPreamble(
3418
this: Destination,
3419
resource: StyleResource,
3420
key: mixed,
3426
// Set on flush but to ensure correct semantics we don't emit
3427
// anything if we are in this state.
3428
set.delete(resource);
3297
- } else if (resource.state & Blocked) {
3298
- // We can't flush but we can preload. We will do this in a second pass
3429
} else {
3300
- didFlush = true;
3430
// We can emit this style or stylesheet as is.
3302
-
3303
- if (resource.type === 'stylesheet') {
3304
- // We still need to encode stylesheet chunks
3305
- // because unlike most Hoistables and Resources we do not eagerly encode
3306
- // them during render. This is because if we flush late we have to send a
3307
- // different encoding and we don't want to encode multiple times
3308
- pushLinkImpl(chunks, resource.props);
3431
+ if (resource.type === 'style') {
3432
+ precedenceStyleTagResource = resource;
3433
+ return;
3434
}
3435
+
3436
+ // We still need to encode stylesheet chunks
3437
+ // because unlike most Hoistables and Resources we do not eagerly encode
3438
+ // them during render. This is because if we flush late we have to send a
3439
+ // different encoding and we don't want to encode multiple times
3440
+ pushLinkImpl(chunks, resource.props);
3441
for (let i = 0; i < chunks.length; i++) {
3442
writeChunk(this, chunks[i]);
3443
}
3444
resource.state |= FlushedInPreamble;
3314
- set.delete(resource);
3445
+ didFlushPrecedence = true;
3446
}
3447
}
3448
3318
-function flushUnblockedStyles(
3319
- this: Destination,
3320
- set: Set<StyleResource>,
3321
- precedence: string,
3322
-) {
3323
- didFlush = false;
3324
- set.forEach(flushUnblockedStyle, this);
3325
- if (!didFlush) {
3326
- // if we did not flush anything for this precedence slot we emit
3327
- // an empty <style data-precedence="..." /> tag to ensure the
3328
- // precedence remains in the correct order
3329
- writeChunk(this, precedencePlaceholderStart);
3330
- writeChunk(this, stringToChunk(escapeTextForBrowser(precedence)));
3331
- writeChunk(this, precedencePlaceholderEnd);
3332
- }
3333
-}
3449
+const styleTagResourceOpen1 = stringToPrecomputedChunk(
3450
+ '<style data-precedence="',
3451
+);
3452
+const styleTagResourceOpen2 = stringToPrecomputedChunk('" data-href="');
3453
+const spaceSeparator = stringToPrecomputedChunk(' ');
3454
+const styleTagResourceOpen3 = stringToPrecomputedChunk('">');
3455
3335
-function preloadBlockedStyle(this: Destination, resource: StyleResource) {
3336
- // The only Resources that should remain are Blocked resources
3337
- if (__DEV__) {
3338
- if ((resource.state & Blocked) === NoState) {
3339
- console.error(
3340
- 'React encountered a Stylesheet Resource that was not Blocked when it was expected to be. This is a bug in React.',
3341
- );
3342
- } else if (resource.state & PreloadFlushed) {
3343
- console.error(
3344
- 'React encountered a Stylesheet Resource that already flushed a Preload when it was not expected to. This is a bug in React.',
3345
- );
3346
- }
3347
- }
3348
- if (resource.type === 'style') {
3349
- // <style> tags do not need to be preloaded
3350
- return;
3351
- }
3352
- const chunks = resource.chunks;
3353
- const preloadProps = preloadAsStylePropsFromProps(
3354
- resource.props.href,
3355
- resource.props,
3356
- );
3357
- pushLinkImpl(chunks, preloadProps);
3358
- for (let i = 0; i < chunks.length; i++) {
3359
- writeChunk(this, chunks[i]);
3360
- }
3361
- resource.state |= PreloadFlushed;
3362
- chunks.length = 0;
3363
-}
3456
+const styleTagResourceClose = stringToPrecomputedChunk('</style>');
3457
3365
-function preloadBlockedStyles(
3458
+function flushAllStylesInPreamble(
3459
this: Destination,
3460
set: Set<StyleResource>,
3461
precedence: string,
3462
) {
3370
- set.forEach(preloadBlockedStyle, this);
3463
+ didFlushPrecedence = false;
3464
+ set.forEach(flushStyleInPreamble, this);
3465
set.clear();
3466
+
3467
+ const chunks = precedenceStyleTagResource.chunks;
3468
+ const hrefs = precedenceStyleTagResource.props.hrefs;
3469
+ if (didFlushPrecedence === false || chunks.length) {
3470
+ writeChunk(this, styleTagResourceOpen1);
3471
+ writeChunk(this, stringToChunk(escapeTextForBrowser(precedence)));
3472
+ let i = 0;
3473
+ if (hrefs.length) {
3474
+ writeChunk(this, styleTagResourceOpen2);
3475
+ for (; i < hrefs.length - 1; i++) {
3476
+ writeChunk(this, stringToChunk(escapeTextForBrowser(hrefs[i])));
3477
+ writeChunk(this, spaceSeparator);
3478
+ }
3479
+ writeChunk(this, stringToChunk(escapeTextForBrowser(hrefs[i])));
3480
+ }
3481
+ writeChunk(this, styleTagResourceOpen3);
3482
+ for (i = 0; i < chunks.length; i++) {
3483
+ writeChunk(this, chunks[i]);
3484
+ }
3485
+ writeChunk(this, styleTagResourceClose);
3486
+
3487
+ // style resources can flush continuously since more rules may be written into
3488
+ // them with new hrefs. Instead of marking it flushed, we simply reset the chunks
3489
+ // and hrefs
3490
+ chunks.length = 0;
3491
+ hrefs.length = 0;
3492
+ }
3493
}
3494
3495
function preloadLateStyle(this: Destination, resource: StyleResource) {
3601
resources.fontPreloads.clear();
3602
3603
// Flush unblocked stylesheets by precedence
3483
- resources.precedences.forEach(flushUnblockedStyles, destination);
3484
-
3485
- // Flush preloads for Blocked stylesheets
3486
- resources.precedences.forEach(preloadBlockedStyles, destination);
3604
+ resources.precedences.forEach(flushAllStylesInPreamble, destination);
3605
3606
resources.usedStylesheets.forEach(resource => {
3607
const key = getResourceKey(resource.props.as, resource.props.href);
3761
}
3762
}
3763
3646
-function hasStyleResourceDependencies(
3647
- boundaryResources: BoundaryResources,
3648
-): boolean {
3649
- const iter = boundaryResources.values();
3650
- // At the moment boundaries only accumulate style resources
3651
- // so we assume the type is correct and don't check it
3652
- while (true) {
3653
- const {value: resource} = iter.next();
3654
- if (!resource) break;
3655
-
3656
- // If every style Resource flushed in the shell we do not need to send
3657
- // any dependencies
3658
- if ((resource.state & FlushedInPreamble) === NoState) {
3659
- return true;
3660
- }
3661
- }
3662
- return false;
3663
-}
3664
-
3764
const arrayFirstOpenBracket = stringToPrecomputedChunk('[');
3765
const arraySubsequentOpenBracket = stringToPrecomputedChunk(',[');
3766
const arrayInterstitial = stringToPrecomputedChunk(',');
3777
3778
let nextArrayOpenBrackChunk = arrayFirstOpenBracket;
3779
boundaryResources.forEach(resource => {
3681
- if (resource.state & FlushedInPreamble) {
3780
+ if (resource.type === 'style') {
3781
+ // Style dependencies don't require coordinated reveal and can be omitted
3782
+ } else if (resource.state & FlushedInPreamble) {
3783
// We can elide this dependency because it was flushed in the shell and
3784
// should be ready before content is shown on the client
3785
} else if (resource.state & Flushed) {
3789
writeChunk(destination, nextArrayOpenBrackChunk);
3790
writeStyleResourceDependencyHrefOnlyInJS(
3791
destination,
3691
- resource.type === 'style'
3692
- ? resource.props['data-href']
3693
- : resource.props.href,
3792
+ resource.props.href,
3793
);
3794
writeChunk(destination, arrayCloseBracket);
3795
nextArrayOpenBrackChunk = arraySubsequentOpenBracket;
3974
3975
let nextArrayOpenBrackChunk = arrayFirstOpenBracket;
3976
boundaryResources.forEach(resource => {
3878
- if (resource.state & FlushedInPreamble) {
3977
+ if (resource.type === 'style') {
3978
+ // Style dependencies don't require coordinated reveal and can be omitted
3979
+ } else if (resource.state & FlushedInPreamble) {
3980
// We can elide this dependency because it was flushed in the shell and
3981
// should be ready before content is shown on the client
3982
} else if (resource.state & Flushed) {
3986
writeChunk(destination, nextArrayOpenBrackChunk);
3987
writeStyleResourceDependencyHrefOnlyInAttr(
3988
destination,
3888
- resource.type === 'style'
3889
- ? resource.props['data-href']
3890
- : resource.props.href,
3989
+ resource.props.href,
3990
);
3991
writeChunk(destination, arrayCloseBracket);
3992
nextArrayOpenBrackChunk = arraySubsequentOpenBracket;
4234
type StylesheetResource = TResource<'stylesheet', StylesheetProps>;
4235
4236
type StyleTagProps = {
4138
- 'data-href': string,
4139
- 'data-precedence': string,
4140
- [string]: mixed,
4237
+ hrefs: Array<string>,
4238
+ precedence: string,
4239
};
4240
type StyleTagResource = TResource<'style', StyleTagProps>;
4241
4266
fontPreloads: Set<PreloadResource>,
4267
// usedImagePreloads: Set<PreloadResource>,
4268
precedences: Map<string, Set<StyleResource>>,
4269
+ stylePrecedences: Map<string, StyleTagResource>,
4270
usedStylesheets: Set<PreloadResource>,
4271
scripts: Set<ScriptResource>,
4272
usedScripts: Set<PreloadResource>,
4294
fontPreloads: new Set(),
4295
// usedImagePreloads: new Set(),
4296
precedences: new Map(),
4297
+ stylePrecedences: new Map(),
4298
usedStylesheets: new Set(),
4299
scripts: new Set(),
4300
usedScripts: new Set(),
4715
if (!precedenceSet) {
4716
precedenceSet = new Set();
4717
resources.precedences.set(precedence, precedenceSet);
4718
+ const emptyStyleResource = {
4719
+ type: 'style',
4720
+ chunks: ([]: Array<Chunk | PrecomputedChunk>),
4721
+ state: NoState,
4722
+ props: {
4723
+ precedence,
4724
+ hrefs: ([]: Array<string>),
4725
+ },
4726
+ };
4727
+ precedenceSet.add(emptyStyleResource);
4728
+ if (__DEV__) {
4729
+ if (resources.stylePrecedences.has(precedence)) {
4730
+ console.error(
4731
+ 'React constructed an empty style resource when a style resource already exists for this precedence: "%s". This is a bug in React.',
4732
+ precedence,
4733
+ );
4734
+ }
4735
+ }
4736
+ resources.stylePrecedences.set(precedence, emptyStyleResource);
4737
}
4738
precedenceSet.add(resource);
4739
}
4888
resourceProps.integrity = preloadProps.integrity;
4889
}
4890
4772
-function styleTagPropsFromRawProps(rawProps: any): StyleTagProps {
4773
- return {
4774
- ...rawProps,
4775
- 'data-precedence': rawProps.precedence,
4776
- precedence: null,
4777
- 'data-href': rawProps.href,
4778
- href: null,
4779
- };
4780
-}
4781
-
4891
function scriptPropsFromPreinitOptions(
4892
src: string,
4893
options: PreinitOptions,
4910
resourceProps.integrity = preloadProps.integrity;
4911
}
4912
4804
-function hoistStylesheetResource(
4805
- this: BoundaryResources,
4806
- resource: StyleResource,
4807
-) {
4913
+function hoistStyleResource(this: BoundaryResources, resource: StyleResource) {
4914
this.add(resource);
4915
}
4916
4920
): void {
4921
const currentBoundaryResources = resources.boundaryResources;
4922
if (currentBoundaryResources) {
4817
- source.forEach(hoistStylesheetResource, currentBoundaryResources);
4818
- source.clear();
4923
+ source.forEach(hoistStyleResource, currentBoundaryResources);
4924
}
4925
}
4926
4822
-function unblockStylesheet(resource: StyleResource) {
4823
- resource.state &= ~Blocked;
4824
-}
4825
-
4826
-export function hoistResourcesToRoot(
4827
- resources: Resources,
4828
- boundaryResources: BoundaryResources,
4829
-): void {
4830
- boundaryResources.forEach(unblockStylesheet);
4831
- boundaryResources.clear();
4832
-}
4833
-
4927
function markAsRenderedResourceDEV(
4928
resource: Resource,
4929
originalProps: any,