diff --git a/README.md b/README.md index 1689467..e8ab06e 100644 --- a/README.md +++ b/README.md @@ -8,14 +8,16 @@ This repo contains a build script for clangd on WebAssembly (TBD), and an exampl I'm working on the build instruction, but you can take a look at `build.sh`. +## About the example page + +I've publish a [GitHub Page](https://clangd.guyutongxue.site/) for demonstrating how clangd works in your browser. + +Notice that clangd is a multi-thread program, so we need `SharedArrayBuffer` -- and more over, a strict context called `crossOriginIsolated`. GitHub Pages do not send COOP/COEP headers for us to enabling that context, so I served this site through CloudFlare with a custom rule adding those headers. If you want to deploy this project by yourself, make sure correct COOP/COEP header is set on the server side, or you can use [`coi-serviceworker`](https://github.com/gzuidhof/coi-serviceworker). + + + ## Acknowledgement - [soedirgo/llvm-wasm](https://github.com/soedirgo/llvm-wasm) provides a very detailed guide on how to build LLVM to wasm. Better then famous works like [binji/wasm-clang](https://github.com/binji/wasm-clang) or [tbfleming/cib](https://github.com/tbfleming/cib) (but also thank you guys :P); - [nokotan/vscode-clangd](https://github.com/nokotan/vscode-clangd) patch vscode's clangd extension with WASM binary to make it work on vscode-web. Some bugs but useful; no build scripts or further documentation; - [ConorBobbleHat/clangd-wasm](https://github.com/ConorBobbleHat/clangd-wasm) and [ConorBobbleHat/clangd-wasm-core](https://github.com/ConorBobbleHat/clangd-wasm-core); build scripts provided but lack examples on how to use them. - -## About the demo - -I've publish a [GitHub Page](https://clangd.guyutongxue.site/) for demonstrating how clangd works in the browser. Notice that clangd is a multi-thread program, so we need `SharedArrayBuffer` -- and more over, a strict context called `crossOriginIsolated`. GitHub Pages do not send COOP/COEP headers for us to enabling that context, so a Service Worker [`coi-serviceworker`](https://github.com/gzuidhof/coi-serviceworker) is used here. If you want to deploy this project, it's encourage to set correct COOP/COEP header on the server side (then you can remove those coi stuff on the `` part of `index.html`). - - diff --git a/index.html b/index.html index 7d41d12..53ac204 100644 --- a/index.html +++ b/index.html @@ -5,8 +5,6 @@ Clangd Web - -
diff --git a/public/sw.js b/public/sw.js deleted file mode 100644 index 9b1879b..0000000 --- a/public/sw.js +++ /dev/null @@ -1,166 +0,0 @@ -/*! 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 { - (() => { - const reloadedBySelf = window.sessionStorage.getItem("coiReloadedBySelf"); - window.sessionStorage.removeItem("coiReloadedBySelf"); - const coepDegrading = reloadedBySelf == "coepdegrade"; - - // You can customize the behavior of this script through a global `coi` variable. - const coi = { - shouldRegister: () => !reloadedBySelf, - shouldDeregister: () => false, - coepCredentialless: () => true, - coepDegrade: () => true, - doReload: () => window.location.reload(), - quiet: false, - ...window.coi, - }; - - const n = navigator; - const controlling = n.serviceWorker && n.serviceWorker.controller; - - // Record the failure if the page is served by serviceWorker. - if (controlling && !window.crossOriginIsolated) { - window.sessionStorage.setItem("coiCoepHasFailed", "true"); - } - const coepHasFailed = window.sessionStorage.getItem("coiCoepHasFailed"); - - if (controlling) { - // Reload only on the first failure. - const reloadToDegrade = - coi.coepDegrade() && !(coepDegrading || window.crossOriginIsolated); - n.serviceWorker.controller.postMessage({ - type: "coepCredentialless", - value: - reloadToDegrade || (coepHasFailed && coi.coepDegrade()) - ? false - : coi.coepCredentialless(), - }); - if (reloadToDegrade) { - !coi.quiet && console.log("Reloading page to degrade COEP."); - window.sessionStorage.setItem("coiReloadedBySelf", "coepdegrade"); - coi.doReload("coepdegrade"); - } - - 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. Firefox private mode) this won't be available - if (!n.serviceWorker) { - !coi.quiet && - console.error( - "COOP/COEP Service Worker not registered, perhaps due to private mode." - ); - return; - } - - 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." - ); - window.sessionStorage.setItem("coiReloadedBySelf", "updatefound"); - 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." - ); - window.sessionStorage.setItem("coiReloadedBySelf", "notcontrolling"); - coi.doReload(); - } - }, - (err) => { - !coi.quiet && - console.error("COOP/COEP Service Worker failed to register:", err); - } - ); - })(); -}