window.__wrnI18n was undefined in development: the payload shipped as an executable inline script, and a document's CSP nonce is fixed at load, so any such script arriving from a later response is blocked. Client translations and language switching silently had no data. The payload is now a type="application/json" block, which the browser never executes and script-src therefore never applies to. The i18n runtime, CSR navigation, and HMR all read the block instead of matching window.__wrnI18n= with a regex. Pages now render zero executable inline scripts, so an inline script-src violation is structurally impossible rather than merely unobserved. Zero framework JavaScript on island-free routes is unaffected: the block is inert data, and nothing loads to read it unless the page needs it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
26 lines
1.1 KiB
TypeScript
26 lines
1.1 KiB
TypeScript
import { expect, test } from "bun:test";
|
|
import { I18N_RUNTIME, renderI18nData, renderI18nDataTag, resolveI18n } from "../src/index.ts";
|
|
|
|
const i18n = resolveI18n({ en: { hello: "Hello" }, es: { hello: "Hola" } }, { default: "en" });
|
|
|
|
test("the i18n payload is plain JSON, not an assignment", () => {
|
|
const data = renderI18nData(i18n, "en");
|
|
expect(() => JSON.parse(data)).not.toThrow();
|
|
expect(data).not.toContain("window.__wrnI18n");
|
|
});
|
|
|
|
test("the data tag is a non-executable JSON block", () => {
|
|
// An executable inline script is subject to script-src and gets blocked
|
|
// whenever the document's CSP nonce came from a different response, which is
|
|
// what left window.__wrnI18n undefined. A JSON block is never executed.
|
|
const tag = renderI18nDataTag(i18n, "es");
|
|
expect(tag).toContain('type="application/json"');
|
|
expect(tag).toContain("data-wrn-i18n");
|
|
expect(tag).not.toContain("nonce=");
|
|
expect(tag).toContain("Hola");
|
|
});
|
|
|
|
test("the i18n runtime reads the data block instead of relying on an inline assignment", () => {
|
|
expect(I18N_RUNTIME).toContain('script[type="application/json"][data-wrn-i18n]');
|
|
});
|