Keep custom element registration safe when in-place navigation reloads the private services bundle. Exercise repeated bundle evaluation with a registry that rejects duplicate definitions.
- commit
- 8511cabfbc945b0eea651b79615bd40d60c8cb09
- parent
- 5651305803654c1ad0b7a74247cf0425f6067cdc
- author
- Dami <dami.etoile@gmail.com>
| M | internal/ | 5 | ++++- |
| M | scripts/ | 8 | +++++++- |
@@ -194,5 +194,8 @@
194194 });195195 window.tiny = window.tiny || {};196196 window.tiny.files = {...window.tiny.files, privateServices: api};197- customElements.define("private-services", PrivateServices);197+ // In-place navigation can request this bundle after a page already loaded198+ // it. Keep the browser's one-definition rule intact while refreshing the199+ // shared API above.200+ if (!customElements.get("private-services")) customElements.define("private-services", PrivateServices);198201 })();@@ -6,10 +6,11 @@ import vm from "node:vm";
66 const shared = await readFile(new URL("../internal/webui/tiny.js", import.meta.url), "utf8");77 const source = await readFile(new URL("../internal/webui/private-services.js", import.meta.url), "utf8");88 class Element {}9+const definitions = new Map();910 const sandbox = {1011 URL, TextEncoder, HTMLElement: Element,1112 document: {}, Response,12- customElements: {define() {}},13+ customElements: {define(name, value) { if (definitions.has(name)) throw Error("duplicate definition"); definitions.set(name, value); }, get(name) { return definitions.get(name); }},1314 tinySigner: {1415 getPublicKey: async () => "a".repeat(64),1516 nip44Encrypt: async (_pubkey, value) => "enc:" + value,@@ -23,6 +24,11 @@ sandbox.window = sandbox;
2324 vm.runInNewContext(shared + source, sandbox);2425 const api = sandbox.tiny.files.privateServices;2526 27+test("can be evaluated again after in-place navigation", async () => {28+ assert.doesNotThrow(() => vm.runInNewContext(source, sandbox));29+ assert.equal(definitions.size, 1);30+});31+2632 test("accepts tenant paths while rejecting unsafe relay URLs", () => {2733 assert.equal(api.validURL("wss://Relay.Example/r/Private"), true);2834 assert.equal(api.canonicalURL("wss://Relay.Example/r/Private/"), "wss://relay.example/r/Private");