ykhrustalev Paulescu commited on
Commit
04fa39a
·
1 Parent(s): c72d46d

Fix cross-origin isolation to resolve TTS crash and slow ASR on HuggingFace (#4)

Browse files

- Add cross-origin isolation via service worker to fix TTS and ASR on HuggingFace (934bcfd49b68a209e8d0a1e8681a099962229a5f)
- Fix infinite reload loop in coi-serviceworker on HuggingFace (d85d217bc786d098d9fb5cd24f307223359ed6ab)


Co-authored-by: Pau Labarta Bajo <Paulescu@users.noreply.huggingface.co>

Files changed (3) hide show
  1. index.html +1 -0
  2. public/coi-serviceworker.js +76 -0
  3. vite.config.js +6 -0
index.html CHANGED
@@ -613,6 +613,7 @@
613
 
614
  <div class="drop-overlay" id="dropOverlay">Drop audio file here</div>
615
 
 
616
  <script type="module" src="./main.js"></script>
617
  </body>
618
  </html>
 
613
 
614
  <div class="drop-overlay" id="dropOverlay">Drop audio file here</div>
615
 
616
+ <script src="./coi-serviceworker.js"></script>
617
  <script type="module" src="./main.js"></script>
618
  </body>
619
  </html>
public/coi-serviceworker.js ADDED
@@ -0,0 +1,76 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* coi-serviceworker - enables cross-origin isolation via service worker
2
+ * Based on https://github.com/gzuidhof/coi-serviceworker (MIT License)
3
+ *
4
+ * Without Cross-Origin-Opener-Policy + Cross-Origin-Embedder-Policy headers,
5
+ * SharedArrayBuffer is unavailable, ONNX Runtime WASM falls back to single-threaded,
6
+ * and compute-heavy models (audio_encoder) become unusably slow.
7
+ *
8
+ * This service worker injects those headers on every response so the app works
9
+ * on static hosts (e.g. HuggingFace Spaces) that don't set them server-side.
10
+ */
11
+
12
+ if (typeof window === "undefined") {
13
+ // ---- Service worker context ----
14
+ self.addEventListener("install", () => self.skipWaiting());
15
+ self.addEventListener("activate", (e) => e.waitUntil(self.clients.claim()));
16
+
17
+ self.addEventListener("fetch", (e) => {
18
+ // Skip non-GET and opaque "only-if-cached" requests (Chrome quirk)
19
+ if (
20
+ e.request.cache === "only-if-cached" &&
21
+ e.request.mode !== "same-origin"
22
+ ) {
23
+ return;
24
+ }
25
+
26
+ e.respondWith(
27
+ fetch(e.request)
28
+ .then((r) => {
29
+ // Opaque responses can't be modified; return as-is
30
+ if (r.status === 0) return r;
31
+
32
+ const headers = new Headers(r.headers);
33
+ headers.set("Cross-Origin-Opener-Policy", "same-origin");
34
+ headers.set("Cross-Origin-Embedder-Policy", "require-corp");
35
+
36
+ return new Response(r.body, {
37
+ status: r.status,
38
+ statusText: r.statusText,
39
+ headers,
40
+ });
41
+ })
42
+ .catch((err) => {
43
+ console.error("[coi-serviceworker] fetch error:", err);
44
+ })
45
+ );
46
+ });
47
+ } else {
48
+ // ---- Page context: register service worker ----
49
+ if (
50
+ !window.crossOriginIsolated &&
51
+ window.isSecureContext &&
52
+ "serviceWorker" in navigator
53
+ ) {
54
+ navigator.serviceWorker
55
+ .register(document.currentScript.src)
56
+ .then((reg) => {
57
+ // SW already active but page loaded without isolation: reload once to activate headers.
58
+ // Guard with sessionStorage to avoid an infinite loop in contexts where
59
+ // crossOriginIsolated can never become true (e.g. HuggingFace iframe embeds).
60
+ if (reg.active && !window.crossOriginIsolated) {
61
+ if (!sessionStorage.getItem("coi-reloaded")) {
62
+ sessionStorage.setItem("coi-reloaded", "1");
63
+ window.location.reload();
64
+ }
65
+ }
66
+ })
67
+ .catch((err) =>
68
+ console.warn("[coi-serviceworker] registration failed:", err)
69
+ );
70
+
71
+ // Reload whenever the SW takes control (first install or update)
72
+ navigator.serviceWorker.addEventListener("controllerchange", () =>
73
+ window.location.reload()
74
+ );
75
+ }
76
+ }
vite.config.js CHANGED
@@ -15,4 +15,10 @@ export default defineConfig({
15
  'Cross-Origin-Embedder-Policy': 'require-corp',
16
  },
17
  },
 
 
 
 
 
 
18
  });
 
15
  'Cross-Origin-Embedder-Policy': 'require-corp',
16
  },
17
  },
18
+ preview: {
19
+ headers: {
20
+ 'Cross-Origin-Opener-Policy': 'same-origin',
21
+ 'Cross-Origin-Embedder-Policy': 'require-corp',
22
+ },
23
+ },
24
  });