From 89d358d8a7b386f4b8a4acbdec04523d17d59b5f Mon Sep 17 00:00:00 2001 From: wxiaoguang Date: Tue, 28 Apr 2026 07:08:50 +0800 Subject: [PATCH] Fix script error alert (#37458) After using CSP nonce, the "onerror" doesn't work anymore. Change it to use a global variable to detect Also help users like #37379 to catch errors more easily. Co-authored-by: Lunny Xiao --- services/context/context_template.go | 23 ++--------------------- templates/base/footer.tmpl | 3 +++ web_src/js/globals.d.ts | 1 + web_src/js/index.ts | 2 ++ web_src/js/vitest.setup.ts | 1 + 5 files changed, 9 insertions(+), 21 deletions(-) diff --git a/services/context/context_template.go b/services/context/context_template.go index b63aaf4c3c3..0f083d097e3 100644 --- a/services/context/context_template.go +++ b/services/context/context_template.go @@ -5,13 +5,11 @@ package context import ( "context" - "fmt" "html" "html/template" "net/http" "strconv" "strings" - "sync" "time" "code.gitea.io/gitea/modules/httplib" @@ -91,31 +89,14 @@ func (c TemplateContext) AppFullLink(link ...string) template.URL { return template.URL(s + "/" + strings.TrimPrefix(link[0], "/")) } -var globalVars = sync.OnceValue(func() (ret struct { - scriptImportRemainingPart string -}, -) { - // add onerror handler to alert users when the script fails to load: - // * for end users: there were many users reporting that "UI doesn't work", actually they made mistakes in their config - // * for developers: help them to remember to run "make watch-frontend" to build frontend assets - // the message will be directly put in the onerror JS code's string - onScriptErrorPrompt := `Please make sure the asset files can be accessed.` - if !setting.IsProd { - onScriptErrorPrompt += `\n\nFor development, run: make watch-frontend.` - } - onScriptErrorJS := fmt.Sprintf(`alert('Failed to load asset file from ' + this.src + '. %s')`, onScriptErrorPrompt) - ret.scriptImportRemainingPart = `onerror="` + html.EscapeString(onScriptErrorJS) + `">` - return ret -}) - func (c TemplateContext) ScriptImport(path string, typ ...string) template.HTML { if len(typ) > 0 { if typ[0] == "module" { - return template.HTML(``) } panic("unsupported script type: " + typ[0]) } - return template.HTML(``) } func (c TemplateContext) CspScriptNonce() (ret string) { diff --git a/templates/base/footer.tmpl b/templates/base/footer.tmpl index 5a218bb62ad..b7443345ada 100644 --- a/templates/base/footer.tmpl +++ b/templates/base/footer.tmpl @@ -11,5 +11,8 @@ {{template "base/footer_content" .}} {{ctx.ScriptImport "js/index.js" "module"}} {{template "custom/footer" .}} + diff --git a/web_src/js/globals.d.ts b/web_src/js/globals.d.ts index bd9fd410b8b..5398d407d1d 100644 --- a/web_src/js/globals.d.ts +++ b/web_src/js/globals.d.ts @@ -53,6 +53,7 @@ interface Window { enableTimeTracking: boolean, mermaidMaxSourceCharacters: number, i18n: Record, + frontendInited: boolean, }, $: JQueryStatic, jQuery: JQueryStatic, diff --git a/web_src/js/index.ts b/web_src/js/index.ts index d6457a13260..cb2b56a5bd5 100644 --- a/web_src/js/index.ts +++ b/web_src/js/index.ts @@ -171,3 +171,5 @@ const initDur = performance.now() - initStartTime; if (initDur > 500) { console.error(`slow init functions took ${initDur.toFixed(3)}ms`); } + +window.config.frontendInited = true; diff --git a/web_src/js/vitest.setup.ts b/web_src/js/vitest.setup.ts index 229c99cceba..190196cabd6 100644 --- a/web_src/js/vitest.setup.ts +++ b/web_src/js/vitest.setup.ts @@ -12,6 +12,7 @@ window.config = { enableTimeTracking: true, mermaidMaxSourceCharacters: 5000, i18n: {}, + frontendInited: false, }; window.testModules = {};