diff --git a/pkg/api/webassets/testdata/sample-assets-manifest.json b/pkg/api/webassets/testdata/sample-assets-manifest.json index cc5f3bc1dcc..96a6ac9f250 100644 --- a/pkg/api/webassets/testdata/sample-assets-manifest.json +++ b/pkg/api/webassets/testdata/sample-assets-manifest.json @@ -20,6 +20,10 @@ "public/build/grot-completed-D-h3ZMGB.svg" ] }, + "_braintree-CW7sY1ng.js": { + "file": "public/build/braintree-CW7sY1ng.js", + "name": "braintree" + }, "_viridis--y8fz-dE.js": { "file": "public/build/viridis--y8fz-dE.js", "name": "viridis", @@ -107,6 +111,15 @@ "public/build/outlier_bg-hJPFLdCg.wasm" ] }, + "app/core/trustedTypePolicies.ts": { + "file": "public/build/trustedTypePolicies-pOmZ7Wr2.js", + "name": "trustedTypePolicies", + "src": "app/core/trustedTypePolicies.ts", + "isEntry": true, + "imports": [ + "_braintree-CW7sY1ng.js" + ] + }, "app/plugins/panel/flamegraph/module.tsx": { "file": "public/build/module-J53A9Kyn.js", "name": "module", diff --git a/pkg/api/webassets/webassets.go b/pkg/api/webassets/webassets.go index 43e17b3244d..77d0b1c813f 100644 --- a/pkg/api/webassets/webassets.go +++ b/pkg/api/webassets/webassets.go @@ -163,7 +163,7 @@ func readWebAssets(r io.Reader) (*dtos.EntryPointAssets, error) { } else { otherJSAssets = append(otherJSAssets, asset) } - preloadJSAssets = getPreloadChunks(manifest, entry.Src) + preloadJSAssets = append(preloadJSAssets, getPreloadChunks(manifest, entry.Src)...) } if entry.Src == "sass/grafana.dark.scss" && entry.IsEntry { darkCSS = entry.File @@ -245,12 +245,11 @@ func readWebAssets(r io.Reader) (*dtos.EntryPointAssets, error) { // Create a list of all the chunks that need to be preloaded for a given entrypoint. func getPreloadChunks(manifest Manifest, name string) []dtos.EntryPointAsset { seen := make(map[string]bool) + var chunks []dtos.EntryPointAsset - var getImportedChunks func(chunk ViteManifestEntry) []dtos.EntryPointAsset - - getImportedChunks = func(chunk ViteManifestEntry) []dtos.EntryPointAsset { - var chunks []dtos.EntryPointAsset + var getImportedChunks func(chunk ViteManifestEntry) + getImportedChunks = func(chunk ViteManifestEntry) { for _, file := range chunk.Imports { importee, exists := manifest[file] if !exists { @@ -261,15 +260,16 @@ func getPreloadChunks(manifest Manifest, name string) []dtos.EntryPointAsset { } seen[file] = true - chunks = append(chunks, getImportedChunks(importee)...) + getImportedChunks(importee) - chunks = append(chunks, dtos.EntryPointAsset{ - FilePath: importee.File, - Integrity: "", - }) + if !seen[importee.File] { + chunks = append(chunks, dtos.EntryPointAsset{ + FilePath: importee.File, + Integrity: "", + }) + seen[importee.File] = true + } } - - return chunks } entryChunk, exists := manifest[name] @@ -277,5 +277,6 @@ func getPreloadChunks(manifest Manifest, name string) []dtos.EntryPointAsset { return nil } - return getImportedChunks(entryChunk) + getImportedChunks(entryChunk) + return chunks } diff --git a/pkg/api/webassets/webassets_test.go b/pkg/api/webassets/webassets_test.go index 5569e702982..bdf9ed5d966 100644 --- a/pkg/api/webassets/webassets_test.go +++ b/pkg/api/webassets/webassets_test.go @@ -3,38 +3,61 @@ package webassets import ( "context" "encoding/json" + "sort" "testing" + "github.com/grafana/grafana/pkg/api/dtos" "github.com/stretchr/testify/require" ) +func sortAssets(assets *dtos.EntryPointAssets) { + sort.Slice(assets.JSFiles, func(i, j int) bool { + return assets.JSFiles[i].FilePath < assets.JSFiles[j].FilePath + }) + sort.Slice(assets.PreloadJSFiles, func(i, j int) bool { + return assets.PreloadJSFiles[i].FilePath < assets.PreloadJSFiles[j].FilePath + }) +} + func TestReadWebassets(t *testing.T) { assets, err := readWebAssetsFromFile("testdata/sample-assets-manifest.json") require.NoError(t, err) + sortAssets(assets) + dto, err := json.MarshalIndent(assets, "", " ") require.NoError(t, err) // fmt.Printf("%s\n", string(dto)) require.JSONEq(t, `{ "jsFiles": [ - { - "filePath": "public/build/index-fkCrlmGK.js", - "integrity": "" - } + { + "filePath": "public/build/index-fkCrlmGK.js", + "integrity": "" + }, + { + "filePath": "public/build/trustedTypePolicies-pOmZ7Wr2.js", + "integrity": "" + } ], "dark": "public/build/grafana-B9F4fUOy.css", "light": "public/build/grafana-Cu0f8nVU.css", "preloadJsFiles": [ - { - "filePath": "public/build/vendor-r65R1Ntf.js", - "integrity": "" - } + { + "filePath": "public/build/braintree-CW7sY1ng.js", + "integrity": "" + }, + { + "filePath": "public/build/vendor-r65R1Ntf.js", + "integrity": "" + } ] }`, string(dto)) assets.SetContentDeliveryURL("https://grafana-assets.grafana.net/grafana/10.3.0-64123/") + sortAssets(assets) + dto, err = json.MarshalIndent(assets, "", " ") require.NoError(t, err) // fmt.Printf("%s\n", string(dto)) @@ -42,20 +65,28 @@ func TestReadWebassets(t *testing.T) { require.JSONEq(t, `{ "cdn": "https://grafana-assets.grafana.net/grafana/10.3.0-64123/", "jsFiles": [ - { - "filePath": "https://grafana-assets.grafana.net/grafana/10.3.0-64123/public/build/index-fkCrlmGK.js", - "integrity": "" - } + { + "filePath": "https://grafana-assets.grafana.net/grafana/10.3.0-64123/public/build/index-fkCrlmGK.js", + "integrity": "" + }, + { + "filePath": "https://grafana-assets.grafana.net/grafana/10.3.0-64123/public/build/trustedTypePolicies-pOmZ7Wr2.js", + "integrity": "" + } + ], + "preloadJsFiles": [ + { + "filePath": "https://grafana-assets.grafana.net/grafana/10.3.0-64123/public/build/braintree-CW7sY1ng.js", + "integrity": "" + }, + { + "filePath": "https://grafana-assets.grafana.net/grafana/10.3.0-64123/public/build/vendor-r65R1Ntf.js", + "integrity": "" + } ], "dark": "https://grafana-assets.grafana.net/grafana/10.3.0-64123/public/build/grafana-B9F4fUOy.css", - "light": "https://grafana-assets.grafana.net/grafana/10.3.0-64123/public/build/grafana-Cu0f8nVU.css", - "preloadJsFiles": [ - { - "filePath": "https://grafana-assets.grafana.net/grafana/10.3.0-64123/public/build/vendor-r65R1Ntf.js", - "integrity": "" - } - ] - }`, string(dto)) + "light": "https://grafana-assets.grafana.net/grafana/10.3.0-64123/public/build/grafana-Cu0f8nVU.css" + }`, string(dto)) } func TestReadWebassetsFromCDN(t *testing.T) { @@ -64,6 +95,8 @@ func TestReadWebassetsFromCDN(t *testing.T) { assets, err := readWebAssetsFromCDN(context.Background(), "https://grafana-assets.grafana.net/grafana/10.3.0-64123/") require.NoError(t, err) + sortAssets(assets) + dto, err := json.MarshalIndent(assets, "", " ") require.NoError(t, err) //fmt.Printf("%s\n", string(dto))