diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml
index 1de927a5..346f2cee 100644
--- a/.github/workflows/docs.yml
+++ b/.github/workflows/docs.yml
@@ -50,21 +50,6 @@ jobs:
- name: Build documentation
run: npm run docs:build
- - name: Add COOP/COEP headers for SharedArrayBuffer support
- run: |
- # Create _headers file for Netlify compatibility
- echo "/*" > docs/.vitepress/dist/_headers
- echo " Cross-Origin-Embedder-Policy: require-corp" >> docs/.vitepress/dist/_headers
- echo " Cross-Origin-Opener-Policy: same-origin" >> docs/.vitepress/dist/_headers
-
- # Create .htaccess file for Apache compatibility (GitHub Pages sometimes uses this)
- echo "Header always set Cross-Origin-Embedder-Policy require-corp" > docs/.vitepress/dist/.htaccess
- echo "Header always set Cross-Origin-Opener-Policy same-origin" >> docs/.vitepress/dist/.htaccess
-
- # Create a meta tag fallback in a headers.html file that can be included
- echo '' > docs/.vitepress/dist/headers.html
- echo '' >> docs/.vitepress/dist/headers.html
-
- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
diff --git a/docs/public/_headers b/docs/public/_headers
deleted file mode 100644
index 430bd97c..00000000
--- a/docs/public/_headers
+++ /dev/null
@@ -1,3 +0,0 @@
-/*
- Cross-Origin-Embedder-Policy: require-corp
- Cross-Origin-Opener-Policy: same-origin
\ No newline at end of file
diff --git a/docs/public/coi-serviceworker.js b/docs/public/coi-serviceworker.js
new file mode 100644
index 00000000..72cc6467
--- /dev/null
+++ b/docs/public/coi-serviceworker.js
@@ -0,0 +1,118 @@
+/*! coi-serviceworker v0.1.7 - Guido Zuidhof and contributors, licensed under MIT */
+let coepCredentialless = false;
+if (typeof window === 'undefined') {
+ self.addEventListener("install", () => self.skipWaiting());
+ self.addEventListener("activate", (event) => event.waitUntil(self.clients.claim()));
+
+ self.addEventListener("message", (ev) => {
+ if (!ev.data) {
+ return;
+ } else if (ev.data.type === "deregister") {
+ self.registration
+ .unregister()
+ .then(() => {
+ return self.clients.matchAll();
+ })
+ .then(clients => {
+ clients.forEach((client) => client.navigate(client.url));
+ });
+ } else if (ev.data.type === "coepCredentialless") {
+ coepCredentialless = ev.data.value;
+ }
+ });
+
+ self.addEventListener("fetch", function (event) {
+ const r = event.request;
+ if (r.cache === "only-if-cached" && r.mode !== "same-origin") {
+ return;
+ }
+
+ const request = (coepCredentialless && r.mode === "no-cors")
+ ? new Request(r, {
+ credentials: "omit",
+ })
+ : r;
+ event.respondWith(
+ fetch(request)
+ .then((response) => {
+ if (response.status === 0) {
+ return response;
+ }
+
+ const newHeaders = new Headers(response.headers);
+ newHeaders.set("Cross-Origin-Embedder-Policy",
+ coepCredentialless ? "credentialless" : "require-corp"
+ );
+ if (!coepCredentialless) {
+ newHeaders.set("Cross-Origin-Resource-Policy", "cross-origin");
+ }
+ newHeaders.set("Cross-Origin-Opener-Policy", "same-origin");
+
+ return new Response(response.body, {
+ status: response.status,
+ statusText: response.statusText,
+ headers: newHeaders,
+ });
+ })
+ .catch((e) => console.error(e))
+ );
+ });
+
+} else {
+ (() => {
+ // You can customize the behavior of this script through a global `coi` variable.
+ const coi = {
+ shouldRegister: () => true,
+ shouldDeregister: () => false,
+ coepCredentialless: () => !(window.chrome || window.netscape),
+ doReload: () => window.location.reload(),
+ quiet: false,
+ ...window.coi
+ };
+
+ const n = navigator;
+
+ if (n.serviceWorker && n.serviceWorker.controller) {
+ n.serviceWorker.controller.postMessage({
+ type: "coepCredentialless",
+ value: coi.coepCredentialless(),
+ });
+
+ if (coi.shouldDeregister()) {
+ n.serviceWorker.controller.postMessage({ type: "deregister" });
+ }
+ }
+
+ // If we're already coi: do nothing. Perhaps it's due to this script doing its job, or COOP/COEP are
+ // already set from the origin server. Also if the browser has no notion of crossOriginIsolated, just give up here.
+ if (window.crossOriginIsolated !== false || !coi.shouldRegister()) return;
+
+ if (!window.isSecureContext) {
+ !coi.quiet && console.log("COOP/COEP Service Worker not registered, a secure context is required.");
+ return;
+ }
+
+ // In some environments (e.g. Chrome incognito mode) this won't be available
+ if (n.serviceWorker) {
+ n.serviceWorker.register(window.document.currentScript.src).then(
+ (registration) => {
+ !coi.quiet && console.log("COOP/COEP Service Worker registered", registration.scope);
+
+ registration.addEventListener("updatefound", () => {
+ !coi.quiet && console.log("Reloading page to make use of updated COOP/COEP Service Worker.");
+ coi.doReload();
+ });
+
+ // If the registration is active, but it's not controlling the page
+ if (registration.active && !n.serviceWorker.controller) {
+ !coi.quiet && console.log("Reloading page to make use of COOP/COEP Service Worker.");
+ coi.doReload();
+ }
+ },
+ (err) => {
+ !coi.quiet && console.error("COOP/COEP Service Worker failed to register:", err);
+ }
+ );
+ }
+ })();
+}
diff --git a/docs/public/demos/worker-system/index.html b/docs/public/demos/worker-system/index.html
index d8706b9d..b7621a74 100644
--- a/docs/public/demos/worker-system/index.html
+++ b/docs/public/demos/worker-system/index.html
@@ -173,17 +173,38 @@
+
+
+