Repository: facebook/react
Pull request: Update preload links to support nonce and fetchpriority

<!--
  Thanks for submitting a pull request!
  We appreciate you spending the time to work on these changes. Please provide enough information so that others can review your pull request. The three fields below are mandatory.

  Before submitting a pull request, please make sure the following is done:

  1. Fork [the repository](https://github.com/facebook/react) and create your branch from `main`.
  2. Run `yarn` in the repository root.
  3. If you've fixed a bug or added code that should be tested, add tests!
  4. Ensure the test suite passes (`yarn test`). Tip: `yarn test --watch TestName` is helpful in development.
  5. Run `yarn test --prod` to test in the production environment. It supports the same options as `yarn test`.
  6. If you need a debugger, run `yarn test --debug --watch TestName`, open `chrome://inspect`, and press "Inspect".
  7. Format your code with [prettier](https://github.com/prettier/prettier) (`yarn prettier`).
  8. Make sure your code lints (`yarn lint`). Tip: `yarn linc` to only check changed files.
  9. Run the [Flow](https://flowtype.org/) type checks (`yarn flow`).
  10. If you haven't already, complete the CLA.

  Learn more about contributing: https://reactjs.org/docs/how-to-contribute.html
-->

## Summary

<!--
 Explain the **motivation** for making this change. What existing problem does the pull request solve?
-->

Addresses #26810 and #26781 

Currently when React generates `rel=preload` link tags for script/stylesheet resources, it will not carryover `nonce` and `fetchpriority` values if specified on the original elements.  

This change ensures that the preload links use the `nonce` and `fetchPriority` values if they were specified. 

## How did you test this change?

<!--
  Demonstrate the code is solid. Example: The exact commands you ran and their output, screenshots / videos if the pull request changes the user interface.
  How exactly did you verify that your PR solves the issue you wanted to solve?
  If you leave this empty, your PR will very likely be closed.
-->
Tested the change by building a local copy and using it in my application.
Before the change: 
- Preload links were causing CSP errors
<img width="1308" alt="image" src="https://github.com/facebook/react/assets/6487551/c31dc25d-2460-4c81-a496-477fdc888c19">
- Preload links did not contain `fetchpriority` or `nonce`
<img width="815" alt="image" src="https://github.com/facebook/react/assets/6487551/8c6250f9-36b5-4340-8cc2-3d20c19be161">

After the change, I can confirm that:
- CSP errors are gone
- preload links show `fetchpriority` (for both script and style preloads) and `nonce`(for script preloads)
<img width="949" alt="image" src="https://github.com/facebook/react/assets/6487551/1299e822-af04-4e6d-a72c-0dc78b3ecfd9">




Changed files:
filename: packages/react-dom-bindings/src/server/ReactFizzConfigDOM.js
patch: @@ -5510,6 +5510,7 @@ function preloadAsStylePropsFromProps(href: string, props: any): PreloadProps {
     as: 'style',
     href: href,
     crossOrigin: props.crossOrigin,
+    fetchPriority: props.fetchPriority,
     integrity: props.integrity,
     media: props.media,
     hrefLang: props.hrefLang,
@@ -5523,7 +5524,9 @@ function preloadAsScriptPropsFromProps(href: string, props: any): PreloadProps {
     as: 'script',
     href,
     crossOrigin: props.crossOrigin,
+    fetchPriority: props.fetchPriority,
     integrity: props.integrity,
+    nonce: props.nonce,
     referrerPolicy: props.referrerPolicy,
   };
 }

filename: packages/react-dom/src/__tests__/ReactDOMFloat-test.js
patch: @@ -4531,6 +4531,43 @@ body {
       );
     });
 
+    // @gate enableFloat
+    it('respects attributes defined on the stylesheet element when preloading stylesheets during server rendering', async () => {
+      await act(() => {
+        const {pipe} = renderToPipeableStream(
+          <html>
+            <head>
+              <link rel="stylesheet" fetchPriority="high" href="foo" />
+            </head>
+            <body>
+              <link rel="stylesheet" fetchPriority="low" href="notaresource" />
+              <div>hello world</div>
+            </body>
+          </html>,
+        );
+        pipe(writable);
+      });
+
+      expect(getMeaningfulChildren(document)).toEqual(
+        <html>
+          <head>
+            <link rel="preload" as="style" fetchpriority="high" href="foo" />
+            <link
+              rel="preload"
+              as="style"
+              fetchpriority="low"
+              href="notaresource"
+            />
+            <link rel="stylesheet" fetchpriority="high" href="foo" />
+          </head>
+          <body>
+            <link rel="stylesheet" fetchpriority="low" href="notaresource" />
+            <div>hello world</div>
+          </body>
+        </html>,
+      );
+    });
+
     // @gate enableFloat
     it('hoists stylesheet resources to the correct precedence', async () => {
       await act(() => {
@@ -5913,6 +5950,45 @@ background-color: green;
       );
     });
 
+    // @gate enableFloat
+    it('respects attributes defined on the script element when preloading scripts during server rendering', async () => {
+      await act(() => {
+        const {pipe} = renderToPipeableStream(
+          <html>
+            <head />
+            <body>
+              <script src="foo" fetchPriority="high" nonce="1234" />
+              <script src="bar" fetchPriority="low" nonce="1234" />
+              hello world
+            </body>
+          </html>,
+        );
+        pipe(writable);
+      });
+
+      expect(getMeaningfulChildren(document)).toEqual(
+        <html>
+          <head>
+            <link
+              rel="preload"
+              href="foo"
+              fetchpriority="high"
+              nonce="1234"
+              as="script"
+            />
+            <link
+              rel="preload"
+              href="bar"
+              fetchpriority="low"
+              nonce="1234"
+              as="script"
+            />
+          </head>
+          <body>hello world</body>
+        </html>,
+      );
+    });
+
     // @gate enableFloat
     it('does not create script resources when inside an <svg> context', async () => {
       await act(() => {