@@ -75,15 +75,15 @@ public function renderScriptTags(string $entryName, ?string $packageName = null,
7575 $ tagAttributes = ['rel ' => 'modulepreload ' , 'href ' => $ url ];
7676 $ this ->applyIntegrity ($ tagAttributes , $ reference , $ integrity );
7777 $ tags [] = \sprintf ('<link %s> ' , $ this ->attributes ($ tagAttributes ));
78- $ this ->preload ($ url , 'modulepreload ' );
78+ $ this ->preload ($ url , 'modulepreload ' , null , $ reference , $ integrity );
7979 }
8080
8181 foreach ($ lookup ->getJavaScriptFiles ($ entryName ) as $ reference ) {
8282 $ url = $ this ->url ($ reference , $ packageName );
8383 $ tagAttributes = ['src ' => $ url , 'type ' => 'module ' ] + $ attributes + $ this ->scriptAttributes ;
8484 $ this ->applyIntegrity ($ tagAttributes , $ reference , $ integrity );
8585 $ tags [] = \sprintf ('<script %s></script> ' , $ this ->attributes ($ tagAttributes ));
86- $ this ->preload ($ url , 'preload ' , 'script ' );
86+ $ this ->preload ($ url , 'preload ' , 'script ' , $ reference , $ integrity );
8787 }
8888
8989 return implode ('' , $ tags );
@@ -103,7 +103,7 @@ public function renderLinkTags(string $entryName, ?string $packageName = null, ?
103103 $ tagAttributes = ['rel ' => 'stylesheet ' , 'href ' => $ url ] + $ attributes + $ this ->linkAttributes ;
104104 $ this ->applyIntegrity ($ tagAttributes , $ reference , $ integrity );
105105 $ tags [] = \sprintf ('<link %s> ' , $ this ->attributes ($ tagAttributes ));
106- $ this ->preload ($ url , 'preload ' , 'style ' );
106+ $ this ->preload ($ url , 'preload ' , 'style ' , $ reference , $ integrity );
107107 }
108108
109109 return implode ('' , $ tags );
@@ -161,7 +161,10 @@ private function url(string $reference, ?string $packageName): string
161161 return $ this ->packages ->getUrl ($ reference , $ packageName ?? $ this ->defaultPackage );
162162 }
163163
164- private function preload (string $ url , string $ rel , ?string $ as = null ): void
164+ /**
165+ * @param array<string, string> $integrity
166+ */
167+ private function preload (string $ url , string $ rel , ?string $ as , string $ reference , array $ integrity ): void
165168 {
166169 if (!$ this ->preload || null === $ this ->requestStack || !class_exists (GenericLinkProvider::class)) {
167170 return ;
@@ -176,6 +179,11 @@ private function preload(string $url, string $rel, ?string $as = null): void
176179 if (null !== $ as ) {
177180 $ link = $ link ->withAttribute ('as ' , $ as );
178181 }
182+ // Mirror the tag's SRI onto the preload, or the browser discards the preloaded response as a mismatch.
183+ [$ hash , $ crossorigin ] = $ this ->integrityFor ($ reference , $ integrity );
184+ if (null !== $ hash ) {
185+ $ link = $ link ->withAttribute ('integrity ' , $ hash )->withAttribute ('crossorigin ' , $ crossorigin );
186+ }
179187
180188 $ linkProvider = $ request ->attributes ->get ('_links ' );
181189 if (!$ linkProvider instanceof GenericLinkProvider) {
@@ -190,11 +198,29 @@ private function preload(string $url, string $rel, ?string $as = null): void
190198 */
191199 private function applyIntegrity (array &$ attributes , string $ reference , array $ integrity ): void
192200 {
193- if (!isset ($ integrity [$ reference ])) {
201+ [$ hash , $ crossorigin ] = $ this ->integrityFor ($ reference , $ integrity );
202+ if (null === $ hash ) {
194203 return ;
195204 }
196- $ attributes ['integrity ' ] = $ integrity [$ reference ];
197- $ attributes ['crossorigin ' ] = false === $ this ->crossorigin ? 'anonymous ' : $ this ->crossorigin ;
205+ $ attributes ['integrity ' ] = $ hash ;
206+ $ attributes ['crossorigin ' ] = $ crossorigin ;
207+ }
208+
209+ /**
210+ * Resolves the SRI hash + crossorigin for a reference, so a tag and its preload Link derive them
211+ * from one place and can never drift.
212+ *
213+ * @param array<string, string> $integrity
214+ *
215+ * @return array{0: ?string, 1: string}
216+ */
217+ private function integrityFor (string $ reference , array $ integrity ): array
218+ {
219+ if (!isset ($ integrity [$ reference ])) {
220+ return [null , '' ];
221+ }
222+
223+ return [$ integrity [$ reference ], false === $ this ->crossorigin ? 'anonymous ' : $ this ->crossorigin ];
198224 }
199225
200226 /**
0 commit comments