Repository: pyscript/pyscript
File: pyscriptjs/src/utils.ts (TypeScript)

Code before:
export function showWarning(msg: string): void {
    _createAlertBanner(msg, "warning")
}

export function handleFetchError(e: Error, singleFile: string) {
    //Should we still export full error contents to console?
    // XXX: What happens if I make a typo? i.e. a web server is being used but a file
    // that doesn't exist is being accessed. We should cover this case as well.
    console.warn(`Caught an error in fetchPaths:\r\n ${e.toString()}`);
    let errorContent: string;
    if (e.message.includes('Failed to fetch')) {
        errorContent = `<p>PyScript: Access to local files
        (using "Paths:" in &lt;py-config&gt;)
        is not available when directly opening a HTML file;
        you must use a webserver to serve the additional files.
        See <a style="text-decoration: underline;" href="https://github.com/pyscript/pyscript/issues/257#issuecomment-1119595062">this reference</a>
        on starting a simple webserver with Python.</p>`;
    } else if (e.message.includes('404')) {
        errorContent =
            `<p>PyScript: Loading from file <u>` +
            singleFile +
            `</u> failed with error 404 (File not Found). Are your filename and path are correct?</p>`;
    } else {
        errorContent = `<p>PyScript encountered an error while loading from file: ${e.message} </p>`;
    }
    showWarning(errorContent);
}

export function readTextFromPath(path: string) {
    const request = new XMLHttpRequest();
    request.open('GET', path, false);
    request.send();
    const returnValue = request.responseText;

    return returnValue;
}

export function inJest(): boolean {
    return typeof process === 'object' && process.env.JEST_WORKER_ID !== undefined;
}

export function globalExport(name: string, obj: object) {
    // attach the given object to the global object, so that it is globally
    // visible everywhere. Should be used very sparingly!

    // `window` in the browser, `global` in node
    const _global = window || global;
    _global[name] = obj;
}

export function getAttribute(el: Element, attr: string): string | null {

Review comment (suggestion):
this is a good example of why the new approach is much better than the old one. I think that here we probably made a mistake and unintentionally allowed the execution to continue.

This function is called by `main.ts` when fetching `paths`:
https://github.com/pyscript/pyscript/blob/08d9c2fbf437bf193c1f6702b34203769cb4e22b/pyscriptjs/src/main.ts#L200-L208

If we cannot fetch a `.py` file, it is very likely that the program will break later. So I think it should be an error, not a warning.

Code after:
    _createAlertBanner(msg, "warning")
}

export function handleFetchError(e: Error, singleFile: string) {
    //Should we still export full error contents to console?
    // XXX: What happens if I make a typo? i.e. a web server is being used but a file
    // that doesn't exist is being accessed. We should cover this case as well.
    console.warn(`Caught an error in fetchPaths:\r\n ${e.toString()}`);
    let errorContent: string;
    if (e.message.includes('Failed to fetch')) {
        errorContent = `<p>PyScript: Access to local files
        (using "Paths:" in &lt;py-config&gt;)
        is not available when directly opening a HTML file;
        you must use a webserver to serve the additional files.
        See <a style="text-decoration: underline;" href="https://github.com/pyscript/pyscript/issues/257#issuecomment-1119595062">this reference</a>
        on starting a simple webserver with Python.</p>`;
    } else if (e.message.includes('404')) {
        errorContent =
            `<p>PyScript: Loading from file <u>` +
            singleFile +
            `</u> failed with error 404 (File not Found). Are your filename and path are correct?</p>`;
    } else {
        errorContent = `<p>PyScript encountered an error while loading from file: ${e.message} </p>`;
    }
    // We need to create the banner because `handleFetchError` is called before we
    // use withUserErrorHandler in main.js we are also disabling the log message
    // because it will be logged by the uncaught exception in promise.
    _createAlertBanner(errorContent, "error", false)
    throw new UserError(errorContent)
}

export function readTextFromPath(path: string) {
    const request = new XMLHttpRequest();
    request.open('GET', path, false);
    request.send();
    const returnValue = request.responseText;

    return returnValue;
}

export function inJest(): boolean {
    return typeof process === 'object' && process.env.JEST_WORKER_ID !== undefined;
}

export function globalExport(name: string, obj: object) {
    // attach the given object to the global object, so that it is globally
    // visible everywhere. Should be used very sparingly!

    globalThis[name] = obj;
}