All checks were successful
Deploy / build-deploy (push) Successful in 4m19s
70 lines
2.9 KiB
C++
70 lines
2.9 KiB
C++
/*
|
|
catcrafts.net
|
|
Copyright (C) 2026 Catcrafts
|
|
|
|
The source code of this website is made available for viewing purposes only.
|
|
No permission is granted to copy, modify, distribute, or create derivative works.
|
|
*/
|
|
|
|
// The bug this suite exists for: /demos/raytracer is two segments deep, and
|
|
// every asset the runtime needs was referenced RELATIVE to the document —
|
|
// src="runtime.js", fetch("files.json"), fetch("variants.json"), and the
|
|
// .wasm named by variants.json. So the browser asked for /demos/runtime.js,
|
|
// Caddy's try_files handed back index.html, and the module was blocked for
|
|
// being text/html. Four NS_ERROR_CORRUPTED_CONTENT failures and a blank demo.
|
|
//
|
|
// The server emits <base href="/"> on any page that boots wasm, which fixes
|
|
// all of them at once. These checks pin that, and pin the precondition that
|
|
// makes it safe: nothing else on the page may use a relative URL.
|
|
//
|
|
// Skips (exit 77) when no wasm bundle sits under bin/ — build the web product
|
|
// first. CI re-runs exactly this suite after the wasm build for that reason.
|
|
|
|
import std;
|
|
import Catcrafts.E2eHarness;
|
|
|
|
using namespace Catcrafts::E2e;
|
|
|
|
int main(int argc, char** argv) {
|
|
TestServer srv(argv[1], 8213);
|
|
|
|
const std::string page = srv.Body("/demos/raytracer");
|
|
if (page.find("<script src=") == std::string::npos) {
|
|
std::println("no bundle under bin/, so no boot scripts were emitted — "
|
|
"build the wasm product first");
|
|
return 77;
|
|
}
|
|
|
|
Check(page.find("<base href=\"/\">") != std::string::npos,
|
|
"wasm page sets <base href=\"/\">");
|
|
|
|
// Absolute script srcs regardless of the <base>, so the tags stay correct
|
|
// even if the base is ever removed.
|
|
{
|
|
const std::regex relativeSrc(R"(<script\s[^>]*src="[^"/:])");
|
|
Check(!std::regex_search(page, relativeSrc),
|
|
"every boot script src is absolute");
|
|
}
|
|
|
|
// A <base> rewrites every relative URL in the document, so it is only
|
|
// safe while there are none. If a view ever emits href="x" or a bare
|
|
// "#frag", the base silently retargets it — assert the precondition
|
|
// rather than trusting it.
|
|
{
|
|
const std::regex urlAttr(R"lit((href|src|action)="([^"]*)")lit");
|
|
std::size_t relative = 0;
|
|
for (auto it = std::sregex_iterator(page.begin(), page.end(), urlAttr);
|
|
it != std::sregex_iterator(); ++it) {
|
|
const std::string url = (*it)[2].str();
|
|
const bool absolute = url.starts_with("/")
|
|
|| url.starts_with("http://")
|
|
|| url.starts_with("https://")
|
|
|| url.starts_with("mailto:");
|
|
if (!absolute) ++relative;
|
|
}
|
|
Check(relative == 0, "wasm page has no relative URL for <base> to retarget",
|
|
std::format("{} URL(s) would be retargeted by the base tag", relative));
|
|
}
|
|
|
|
return Finish();
|
|
}
|