All files / src loader.js

89.28% Statements 50/56
79.16% Branches 19/24
100% Functions 12/12
95.55% Lines 43/45

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98    149x     149x                     13x 13x         27x 27x   5x       149x 4x             9x 8x 6x       9x 9x 9x 9x 9x 8x 2x 2x   6x 6x         9x 1x   9x       149x     4x       191x 191x 191x 1x   190x 185x 185x 185x 2x 2x 2x   183x 183x         200x 191x   9x      
import { stringToUint8Array } from "./binary.js";
 
export const runningInNode = typeof window === "undefined";
 
/** Why a disc or tape could not be loaded, in terms general enough to report. */
export const LoadFailures = Object.freeze({
    notFound: "not_found",
    http: "http",
    network: "network",
    unauthorised: "unauthorised",
    badImage: "bad_image",
    other: "other",
});
 
/** `error`, saying it failed for `reason` unless it already says why. */
export function failedFor(error, reason) {
    Eif (!error.loadFailure) error.loadFailure = reason;
    return error;
}
 
/** What `make` resolves to, any failure of it failing for `reason` unless it already says why. */
export async function failingFor(reason, make) {
    try {
        return await make();
    } catch (error) {
        throw failedFor(error, reason);
    }
}
 
const httpFailure = (url, status) =>
    failedFor(
        new Error(`Unable to load ${url}, http code ${status}`),
        status === 404 ? LoadFailures.notFound : LoadFailures.http,
    );
 
/** The bytes at `url`, fetched, failing as `not_found`, `http` or `network`. */
export async function fetchBytes(url) {
    const response = await failingFor(LoadFailures.network, () => fetch(url));
    if (!response.ok) throw httpFailure(url, response.status);
    return new Uint8Array(await response.arrayBuffer());
}
 
function loadDataHttp(url) {
    return new Promise(function (resolve, reject) {
        const request = new XMLHttpRequest();
        request.open("GET", url, true);
        request.overrideMimeType("text/plain; charset=x-user-defined");
        request.onload = function () {
            if (request.status !== 200) {
                reject(httpFailure(url, request.status));
                return;
            }
            if (typeof request.response !== "string") {
                resolve(request.response);
            } else E{
                resolve(stringToUint8Array(request.response));
            }
        };
        request.onerror = function () {
            reject(failedFor(new Error(`A network error occurred loading ${url}`), LoadFailures.network));
        };
        request.send(null);
    });
}
 
let _nodeBasePath = null;
 
export function setNodeBasePath(basePath) {
    _nodeBasePath = basePath;
}
 
async function loadDataNode(url) {
    if (url.startsWith("file:")) {
        const fs = await import("fs");
        const { fileURLToPath } = await import("url");
        return fs.readFileSync(fileURLToPath(url));
    }
    if (/^https?:\/\//.test(url)) return fetchBytes(url);
    const fs = await import("fs");
    const nodePath = await import("path");
    if (_nodeBasePath) {
        const publicPath = nodePath.join(_nodeBasePath, "public", url);
        Iif (fs.existsSync(publicPath)) return fs.readFileSync(publicPath);
        return fs.readFileSync(nodePath.join(_nodeBasePath, url));
    }
    Iif (url[0] === "/") url = "." + url;
    Eif (fs.existsSync("public/" + url)) return fs.readFileSync("public/" + url);
    return fs.readFileSync(url);
}
 
export function loadData(url) {
    if (runningInNode) {
        return loadDataNode(url);
    } else {
        return loadDataHttp(url);
    }
}