@virtualstate/app-history
Version:
Native JavaScript [app-history](https://github.com/WICG/app-history) implementation
108 lines (106 loc) • 4.09 kB
JavaScript
import { createServer } from "http";
import { resolve, dirname, join } from "path";
import * as Cheerio from "cheerio";
import { promises as fs } from "fs";
const namespacePath = "/node_modules/wpt";
const buildPath = "/esnext";
const resourcesInput = "/resources";
const resourcesTarget = "/node_modules/wpt/resources";
export function startServer(port) {
const server = createServer((request, response) => {
const url = new URL(request.url, `http://localhost:${port}`);
let promise = Promise.resolve("");
response.setHeader("Access-Control-Allow-Origin", "*");
console.log({ pathname: url.pathname });
if (url.pathname.endsWith(".html.js")) {
promise = createJavaScriptBundle(url);
response.setHeader("Content-Type", "application/javascript");
}
promise
.then(contents => {
response.writeHead(200);
response.write(contents);
})
.catch((error) => {
console.log({ error });
response.writeHead(500);
})
.then(() => response.end());
});
server.listen(port, () => {
console.log(`Running Web Platform Tests ECMAScript Modules server on port ${port}`);
});
return () => {
};
}
export async function createJavaScriptBundle(url) {
const cwd = resolve(dirname(new URL(import.meta.url).pathname), "../..");
const withoutExtension = url.pathname.replace(/\.html\.js$/, "");
console.log({ cwd, withoutExtension });
if (withoutExtension.includes("."))
throw new Error("Unexpected dot in path");
const htmlPath = join(cwd, namespacePath, `${withoutExtension}.html`);
console.log({ cwd, withoutExtension, htmlPath });
const html = await fs.readFile(htmlPath, "utf-8");
if (!html)
return "";
const $ = Cheerio.load(html);
const dependencies = await Promise.all($("script[src]")
.map(function () {
return $(this).attr("src");
})
.toArray()
.filter(dependency => url.searchParams.get("localDependenciesOnly") ? !dependency.startsWith("/") : true)
.map(async (dependency) => [
dependency,
await fs.readFile(join(cwd, namespacePath, new URL(dependency, url.toString()).pathname), "utf-8").catch(() => "// Could not load")
]));
const dependenciesJoined = `
//
const self = globalThis;
${dependencies
.map(([name, contents]) => `// ${name.replace(cwd, "")}\n${contents}`)
.join("\n")}
`;
const scripts = $("script:not([src])")
.map(function () {
return $(this).html() ?? "";
})
.toArray();
let scriptsJoined = scripts.join('\n');
if (url.searchParams.get("preferUndefined")) {
// eek
scriptsJoined = scriptsJoined.replace(/null/g, "undefined");
}
let fnName = url.searchParams.get("exportAs");
// https://stackoverflow.com/a/2008353/1174869
const identifierTest = /^[$A-Z_][0-9A-Z_$]*$/i;
if (!fnName || !identifierTest.test(fnName)) {
fnName = "runTests";
}
let globalNames = (url.searchParams.get("globals") ?? "")
.split(",")
.filter(name => identifierTest.test(name));
if (!globalNames.length) {
globalNames = ["______globals_object_key"];
}
const globalsDestructure = `{${globalNames.join(", ")}}`;
const scriptHarness = `
export function ${fnName}(${globalsDestructure}) {${url.searchParams.get("debugger") ? "\nconsole.log('debugger start');debugger;\n" : ""}
${scriptsJoined}
}
`.trim();
if (url.searchParams.get("dependenciesOnly")) {
return dependenciesJoined;
}
if (url.searchParams.get("scriptsOnly")) {
return scriptHarness;
}
return `${dependenciesJoined}\n${scriptHarness}`;
}
if (typeof process !== "undefined" && process.argv.includes(new URL(import.meta.url).pathname)) {
const portString = process.env.PORT || '';
const port = /^\d+$/.test(portString) ? +portString : 3000;
void startServer(port);
}
//# sourceMappingURL=app-history.server.wpt.js.map